&userbuf, MAILROOM);
CtdlSaveMsgPointerInRoom(actual_rm, newmsgid, 0, msg);
BumpNewMailCounter(userbuf.usernum);
+ if (strlen(config.c_funambol_host) > 0) {
+ /* Generate a instruction message for the Funambol notification
+ server, in the same style as the SMTP queue */
+ instr = malloc(SIZ * 2);
+ snprintf(instr, SIZ * 2,
+ "Content-type: %s\n\nmsgid|%ld\nsubmitted|%ld\n"
+ "bounceto|%s@%s\n",
+ SPOOLMIME, newmsgid, (long)time(NULL),
+ msg->cm_fields['A'], msg->cm_fields['N']
+ );
+
+ imsg = malloc(sizeof(struct CtdlMessage));
+ memset(imsg, 0, sizeof(struct CtdlMessage));
+ imsg->cm_magic = CTDLMESSAGE_MAGIC;
+ imsg->cm_anon_type = MES_NORMAL;
+ imsg->cm_format_type = FMT_RFC822;
+ imsg->cm_fields['A'] = strdup("Citadel");
+ imsg->cm_fields['J'] = strdup("do not journal");
+ imsg->cm_fields['M'] = instr;
+ imsg->cm_fields['W'] = strdup(recipient);
+ CtdlSubmitMsg(imsg, NULL, FNBL_QUEUE_ROOM);
+ CtdlFreeMessage(imsg);
+ }
}
else {
lprintf(CTDL_DEBUG, "No user <%s>\n", recipient);
void do_system_configuration(CtdlIPC *ipc)
{
-#define NUM_CONFIGS 52
+#define NUM_CONFIGS 57
char buf[256];
char sc[NUM_CONFIGS][256];
else {
sc[18][0] = 0;
}
-
+ snprintf(sc[52], sizeof sc[52], "%d", (boolprompt(
+ "Use system authentication",
+ atoi(&sc[52][0]))));
/* Server tuning */
strprompt("SMTPS server port (-1 to disable)", &sc[41][0], 5);
strprompt("Postfix TCP Dictionary Port server port (-1 to disable)", &sc[50][0], 5);
strprompt("ManageSieve server port (-1 to disable)", &sc[51][0], 5);
-
/* This logic flips the question around, because it's one of those
* situations where 0=yes and 1=no
*/
&sc[48][0], 127);
}
+ /* Funambol push stuff */
+ strprompt("Funambol server (blank to disable)", &sc[53][0], 63);
+ strprompt("Funambol server port", &sc[54][0], 5);
+ strprompt("Funambol sync source", &sc[55][0], 63);
+ strprompt("Funambol authentication details (user:pass in Base64)", &sc[56][0],63);
+
/* Save it */
scr_printf("Save this configuration? ");
if (yesno()) {
/*
* This module implements a notifier for Funambol push email.
+ * Based on bits of serv_spam, serv_smtp
*/
#define FUNAMBOL_WS "/funambol/services/admin"
#include "internet_addressing.h"
#include "domain.h"
#include "clientsocket.h"
+#include "serv_funambol.h"
+/*
+ * Create the notify message queue
+ */
+void create_notify_queue(void) {
+ struct ctdlroom qrbuf;
+ create_room(FNBL_QUEUE_ROOM, 3, "", 0, 1, 0, VIEW_MAILBOX);
-
+ /*
+ * Make sure it's set to be a "system room" so it doesn't show up
+ * in the <K>nown rooms list for Aides.
+ */
+ if (lgetroom(&qrbuf, FNBL_QUEUE_ROOM) == 0) {
+ qrbuf.QRflags2 |= QR2_SYSTEM;
+ lputroom(&qrbuf);
+ }
+}
/*
* Connect to the Funambol server and scan a message.
*/
-int notify_funambol(struct CtdlMessage *msg) {
+int notify_funambol(long msgnum, void *userdata) {
+ struct CtdlMessage *msg;
int sock = (-1);
char buf[SIZ];
char SOAPHeader[SIZ];
char SOAPData[SIZ];
char port[SIZ];
/* W means 'Wireless'... */
+ msg = CtdlFetchMessage(msgnum, 1);
if ( msg->cm_fields['W'] == NULL) {
return(0);
}
} else {
lprintf(CTDL_INFO, "Push enabled\n");
}
+
sprintf(port, "%d", config.c_funambol_port);
lprintf(CTDL_INFO, "Connecting to Funambol at <%s>\n", config.c_funambol_host);
sock = sock_connect(config.c_funambol_host, port, "tcp");
if (sock >= 0) lprintf(CTDL_DEBUG, "Connected!\n");
if (sock < 0) {
- /* If the service isn't running, just pass the mail
- * through. Potentially throwing away mails isn't good.
- */
+ /* If the service isn't running, pass for now */
return(0);
}
/* Build a SOAP message, delicately, by hand */
- strcat(SOAPData, "<?xml version=\"1.0\" encoding=\"UTF-8\"?><soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">");
+ sprintf(SOAPData, "<?xml version=\"1.0\" encoding=\"UTF-8\"?><soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">");
strcat(SOAPData, "<soapenv:Body><sendNotificationMessages soapenv:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">");
strcat(SOAPData, "<arg0 xsi:type=\"soapenc:string\" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">");
strcat(SOAPData, msg->cm_fields['W']);
}
lprintf(CTDL_DEBUG, "<%s\n", buf);
if (strncasecmp(buf, "HTTP/1.1 200 OK", strlen("HTTP/1.1 200 OK"))) {
+
goto bail;
}
lprintf(CTDL_DEBUG, "Funambol notified\n");
-
-bail: close(sock);
- return(0);
+ /* We should allow retries here but for now purge after one go */
+ bail:
+ CtdlFreeMessage(msg);
+ long todelete[1];
+ todelete[0] = msgnum;
+ CtdlDeleteMessages(FNBL_QUEUE_ROOM, todelete, 1, "");
+ close(sock);
+ return 0;
}
+void do_notify_queue(void) {
+ static int doing_queue = 0;
+
+ /*
+ * This is a simple concurrency check to make sure only one queue run
+ * is done at a time. We could do this with a mutex, but since we
+ * don't really require extremely fine granularity here, we'll do it
+ * with a static variable instead.
+ */
+ if (doing_queue) return;
+ doing_queue = 1;
+
+ /*
+ * Go ahead and run the queue
+ */
+ lprintf(CTDL_INFO, "serv_funambol: processing notify queue\n");
+
+ if (getroom(&CC->room, FNBL_QUEUE_ROOM) != 0) {
+ lprintf(CTDL_ERR, "Cannot find room <%s>\n", FNBL_QUEUE_ROOM);
+ return;
+ }
+ CtdlForEachMessage(MSGS_ALL, 0L, NULL,
+ SPOOLMIME, NULL, notify_funambol, NULL);
+
+ lprintf(CTDL_INFO, "serv_funambol: queue run completed\n");
+ doing_queue = 0;
+}
+
char *serv_funambol_init(void)
{
- CtdlRegisterMessageHook(notify_funambol, EVT_AFTERSAVE);
+ create_notify_queue();
+ CtdlRegisterSessionHook(do_notify_queue, EVT_TIMER);
return "$Id: serv_funambol.c $";
}
cprintf("%d\n", config.c_pftcpdict_port);
cprintf("%d\n", config.c_managesieve_port);
cprintf("%d\n", config.c_auth_mode);
-
+ cprintf("%s\n", config.c_funambol_host);
+ cprintf("%d\n", config.c_funambol_port);
+ cprintf("%s\n", config.c_funambol_source);
+ cprintf("%s\n", config.c_funambol_auth);
/* Export the control file */
get_control();
client_getln(buf, sizeof buf); config.c_pftcpdict_port = atoi(buf);
client_getln(buf, sizeof buf); config.c_managesieve_port = atoi(buf);
client_getln(buf, sizeof buf); config.c_auth_mode = atoi(buf);
+ client_getln(config.c_funambol_host, sizeof config.c_funambol_host);
+ client_getln(buf, sizeof buf); config.c_funambol_port = atoi(buf);
+ client_getln(config.c_funambol_source, sizeof config.c_funambol_source);
+ client_getln(config.c_funambol_auth, sizeof config.c_funambol_auth);
+
config.c_enable_fulltext = 0; /* always disable */
put_config();
lprintf(CTDL_INFO, "Imported config file\n");