diff --git a/mbuni/ChangeLog b/mbuni/ChangeLog index 5d4ea03..cab1180 100644 --- a/mbuni/ChangeLog +++ b/mbuni/ChangeLog @@ -1,3 +1,5 @@ +2007-03-20 P. A. Bagyenda + * Major corrections to MM4 functionality, bringing conformance to 3GPP TS 23.140 (Thanks to Deon van der Merwe for funding) 2007-03-09 P. A. Bagyenda * Patch to fix panic in the event of missing/corrupt data file in queue (Thanks to Deon van der Merwe ) 2007-01-31 Vincent Chavanis diff --git a/mbuni/doc/userguide.shtml b/mbuni/doc/userguide.shtml index aa30f35..a031e5b 100644 --- a/mbuni/doc/userguide.shtml +++ b/mbuni/doc/userguide.shtml @@ -1880,12 +1880,27 @@ denied-prefix recipient number prefixes that cannot be delivered via this proxy + + + + confirmed-delivery + + + Boolean + + + Specifies whether to use request MM4 acknowledgement from the + recipient MMC for each message. Default is true. + + +

When an MM destined to an MSISDN cannot be delivered locally, the gateway searches the list of Proxies to see if one of them can handle -the message. If one is found, the message is formatted as MIME and +the message. If one is found, the message is formatted as MM4 MIME +(according to 3GPP TS 23.140) and sent via SMTP to the proxy.

diff --git a/mbuni/mmlib/mms_cfg.def b/mbuni/mmlib/mms_cfg.def index 53a4cf7..d67ffce 100644 --- a/mbuni/mmlib/mms_cfg.def +++ b/mbuni/mmlib/mms_cfg.def @@ -91,6 +91,7 @@ MULTI_GROUP(mmsproxy, OCTSTR(host) OCTSTR(allowed-prefix) OCTSTR(denied-prefix) + OCTSTR(confirmed-delivery) ) MULTI_GROUP(mms-vasp, diff --git a/mbuni/mmlib/mms_mm7soap.h b/mbuni/mmlib/mms_mm7soap.h index 999c514..1de765b 100644 --- a/mbuni/mmlib/mms_mm7soap.h +++ b/mbuni/mmlib/mms_mm7soap.h @@ -16,9 +16,10 @@ #define MM7_SOAP_OK 1000 #define MM7_SOAP_FORMAT_CORRUPT 2007 +#define MM7_SOAP_COMMAND_REJECTED 3005 #define MM7_SOAP_UNSUPPORTED_OPERATION 4003 #define MM7_SOAP_STATUS_OK(e) ((e) / 1000 == 1) -#define MM7_DEFAULT_VERSION "5.3.0" +#define MM7_DEFAULT_VERSION MMS_3GPP_VERSION typedef struct MSoapMsg_t MSoapMsg_t; diff --git a/mbuni/mmlib/mms_msg.c b/mbuni/mmlib/mms_msg.c index 2574c7d..3ef9f43 100644 --- a/mbuni/mmlib/mms_msg.c +++ b/mbuni/mmlib/mms_msg.c @@ -1007,6 +1007,7 @@ static int encode_msgheaders(Octstr *os, List *hdrs) static int fixup_msg(MmsMsg *m, Octstr *from) { Octstr *ver; + Octstr *s = NULL; if (!m) return -1; @@ -1018,10 +1019,11 @@ static int fixup_msg(MmsMsg *m, Octstr *from) } else if (octstr_str_compare(ver, "1.2") <= 0) m->enc = MS_1_2; http_header_remove_all(m->headers, "MIME-Version"); - if (m->message_type == MMS_MSGTYPE_SEND_REQ || - m->message_type == MMS_MSGTYPE_RETRIEVE_CONF) { - Octstr *s = NULL; - + switch (m->message_type) { + case MMS_MSGTYPE_SEND_REQ: + case MMS_MSGTYPE_RETRIEVE_CONF: + case MMS_MSGTYPE_FORWARD_REQ: + /* Check for from. */ if (from && (s = http_header_value(m->headers, octstr_imm("From"))) == NULL) http_header_add(m->headers, "From", octstr_get_cstr(from)); @@ -1036,7 +1038,7 @@ static int fixup_msg(MmsMsg *m, Octstr *from) octstr_destroy(t); } else octstr_destroy(s); - + #if 0 /* This will be done elsewhere. */ /* Check for msgid, put in if missing. */ if ((s = http_header_value(m->headers, octstr_imm("Message-ID"))) == NULL) @@ -1059,9 +1061,16 @@ static int fixup_msg(MmsMsg *m, Octstr *from) http_header_add(m->headers, "Content-Type", ctype); } else octstr_destroy(s); + strip_boundary_element(m->headers, NULL); /* remove top-level boundary element if any. */ + break; + case MMS_MSGTYPE_SEND_CONF: + case MMS_MSGTYPE_NOTIFICATION_IND: + case MMS_MSGTYPE_DELIVERY_IND: + case MMS_MSGTYPE_READ_REC_IND: + case MMS_MSGTYPE_READ_ORIG_IND: + http_header_remove_all(m->headers, "Content-Type"); /* Just in case, particularly from mime! */ + break; } - strip_boundary_element(m->headers, NULL); /* remove top-level boundary element if any. */ - return 0; } @@ -1212,13 +1221,13 @@ int mms_messagetype(MmsMsg *msg) static void convert_mime_msg(MIMEEntity *m) { int i, n; - Octstr *content_type, *params; + Octstr *content_type = NULL, *params; char *s = NULL; List *h = mime_entity_headers(m); - get_content_type(h, &content_type, ¶ms); + n = get_content_type(h, &content_type, ¶ms); - if (content_type) { + if (n == 0 && content_type) { if (octstr_str_compare(content_type, "application/vnd.wap.multipart.related") == 0) s = "multipart/related"; @@ -1267,9 +1276,9 @@ static void unconvert_mime_msg(MIMEEntity *m) char *s = NULL; List *h = mime_entity_headers(m); - get_content_type(h, &content_type, ¶ms); + n = get_content_type(h, &content_type, ¶ms); - if (content_type) { + if (n == 0 && content_type) { if (octstr_case_compare(content_type, octstr_imm("multipart/related")) == 0) s = "application/vnd.wap.multipart.related"; diff --git a/mbuni/mmlib/mms_util.c b/mbuni/mmlib/mms_util.c index afdaf49..7ba07b2 100644 --- a/mbuni/mmlib/mms_util.c +++ b/mbuni/mmlib/mms_util.c @@ -177,9 +177,9 @@ Octstr *mms_isodate(time_t t) void mms_lib_init(void) { + srandom(time(NULL)); /* Seed random number generator. */ gwlib_init(); mms_strings_init(); - } void mms_lib_shutdown(void) @@ -470,6 +470,7 @@ static void addmmscname(Octstr *s, Octstr *myhostname) } + static int send2email(Octstr *to, Octstr *from, Octstr *subject, Octstr *msgid, MIMEEntity *m, int append_hostname, Octstr **error, @@ -477,21 +478,61 @@ static int send2email(Octstr *to, Octstr *from, Octstr *subject, { Octstr *s; FILE *f; - int ret = MMS_SEND_OK, i; + int ret = MMS_SEND_OK, i, n; Octstr *cmd = octstr_create(""); List *headers = mime_entity_headers(m); /* we don't want the mime version header removed. */ if (append_hostname) { /* Add our hostname to all phone numbers. */ List *l = http_create_empty_headers(); Octstr *xfrom = http_header_value(headers, octstr_imm("From")); - + List *lto = http_header_find_all(headers, "To"); + List *lcc = http_header_find_all(headers, "Cc"); + if (xfrom) { addmmscname(xfrom, myhostname); http_header_add(l, "From", octstr_get_cstr(xfrom)); octstr_destroy(xfrom); } http_header_remove_all(headers, "From"); + + for (i = 0, n = gwlist_len(lto); i < n; i++) { + Octstr *name, *value; + + http_header_get(lto, i, &name, &value); + + if (!value || !name || + octstr_case_compare(name, octstr_imm("To")) != 0) + goto loop; + + addmmscname(value, myhostname); + http_header_add(l, "To", octstr_get_cstr(value)); + loop: + if (value) octstr_destroy(value); + if (name) octstr_destroy(name); + } + + http_destroy_headers(lto); + http_header_remove_all(headers, "To"); + for (i = 0, n = gwlist_len(lcc); i < n; i++) { + Octstr *name, *value; + + http_header_get(lcc, i, &name, &value); + + if (!value || !name || + octstr_case_compare(name, octstr_imm("Cc")) != 0) + goto loop2; + + addmmscname(value, myhostname); + http_header_add(l, "Cc", octstr_get_cstr(value)); + loop2: + if (value) octstr_destroy(value); + if (name) octstr_destroy(name); + } + + http_destroy_headers(lcc); + http_header_remove_all(headers, "Cc"); + http_append_headers(headers, l); /* combine old with new. */ http_destroy_headers(l); } @@ -589,7 +630,7 @@ static int send2email(Octstr *to, Octstr *from, Octstr *subject, ret, strerror(errno)); ret = MMS_SEND_ERROR_TRANSIENT; } else - ret = MMS_SEND_OK; + ret = MMS_SEND_QUEUED; done: http_destroy_headers(headers); @@ -599,20 +640,33 @@ static int send2email(Octstr *to, Octstr *from, Octstr *subject, } +int mm_send_to_email(Octstr *to, Octstr *from, Octstr *subject, + Octstr *msgid, + MIMEEntity *m, int append_hostname, Octstr **error, + char *sendmail_cmd, Octstr *myhostname) +{ + return send2email(to,from,subject,msgid,m,append_hostname,error,sendmail_cmd,myhostname); +} + /* Send this message to email recipient. */ int mms_sendtoemail(Octstr *from, Octstr *to, Octstr *subject, Octstr *msgid, - MmsMsg *msg, int dlr, Octstr **error, char *sendmail_cmd, + MmsMsg *msg, int dlr, + Octstr **error, char *sendmail_cmd, Octstr *myhostname, int trans_msg, int trans_smil, char *txt, char *html, - int append_hostname) + int mm4, + char *transid) { MIMEEntity *m = NULL; List *headers = NULL; List *newhdrs = http_create_empty_headers(); - int ret; + int ret = 0, mtype; + + gw_assert(msg); + mtype = mms_messagetype(msg); if (!to || octstr_search_char(to, '@', 0) < 0) { @@ -622,40 +676,68 @@ int mms_sendtoemail(Octstr *from, Octstr *to, if (!trans_msg) m = mms_tomime(msg,0); - else - if ((ret = mms_format_special(msg, trans_smil, txt, html, &m)) < 0 || + else if ((ret = mms_format_special(msg, trans_smil, txt, html, &m)) < 0 || m == NULL) { - warning(0, "MMS: send2email failed to format message (msg=%s,ret=%d)", - m ? "OK" : "Not transformed",ret); + warning(0, "MMS: send2email failed to format message (msg=%s,ret=%d)", + m ? "OK" : "Not transformed",ret); return -ret; - } + } base64_mimeparts(m); /* make sure parts are base64 formatted. */ headers = mime_entity_headers(m); /* Before we send it, we insert some email friendly headers if they are missing. */ - http_header_add(newhdrs, "Subject", subject ? octstr_get_cstr(subject) : "MMS Message"); - http_header_remove_all(headers, "From"); - http_header_add(newhdrs, "From", octstr_get_cstr(from)); - http_header_remove_all(headers, "To"); - http_header_add(newhdrs, "To", octstr_get_cstr(to)); - http_header_add(newhdrs, "Message-ID", msgid ? octstr_get_cstr(msgid) : ""); + if (!mm4) { + http_header_add(newhdrs, "Subject", subject ? octstr_get_cstr(subject) : "MMS Message"); + http_header_remove_all(headers, "From"); + http_header_add(newhdrs, "From", octstr_get_cstr(from)); + http_header_remove_all(headers, "To"); + http_header_add(newhdrs, "To", octstr_get_cstr(to)); + http_header_add(newhdrs, "Message-ID", msgid ? octstr_get_cstr(msgid) : ""); + http_header_add(newhdrs, "MIME-Version", "1.0"); + } else { + char *x; + Octstr *xsender = octstr_format("system-user@%S", myhostname); + http_header_add(newhdrs, "X-Mms-Message-ID", msgid ? octstr_get_cstr(msgid) : ""); + + http_header_add(newhdrs, "X-Mms-3GPP-MMS-Version", MMS_3GPP_VERSION); + http_header_add(newhdrs, "X-Mms-Originator-System", + octstr_get_cstr(xsender)); + http_header_remove_all(headers, "X-Mms-Message-Type"); + if (mtype == MMS_MSGTYPE_SEND_REQ || + mtype == MMS_MSGTYPE_RETRIEVE_CONF) + x = "MM4_forward.REQ"; + else if (mtype == MMS_MSGTYPE_DELIVERY_IND) + x = "MM4_delivery_report.REQ"; + else if (mtype == MMS_MSGTYPE_READ_REC_IND) + x = "MM4_read_reply_report.REQ"; + else { + *error = octstr_format("Invalid message type %s on MM4 outgoing interface!", + mms_message_type_to_cstr(mtype)); + x = ""; + ret = MMS_SEND_ERROR_FATAL; + goto done; + } + http_header_add(newhdrs, "X-Mms-Message-Type", x); + /* Add a few more MM4 headers. */ + http_header_add(newhdrs, "X-Mms-Ack-Request", dlr ? "Yes" : "No"); + http_header_add(newhdrs, "Sender", octstr_get_cstr(from)); + http_header_add(newhdrs, "X-Mms-Transaction-ID", transid); - http_header_add(newhdrs, "X-Mms-Message-ID", msgid ? octstr_get_cstr(msgid) : ""); - http_header_add(newhdrs, "MIME-Version", "1.0"); - http_header_add(newhdrs, "X-Mms-3GPP-MMS-Version", "5.5.0"); - http_header_add(newhdrs, "X-Mms-Originator-System", myhostname ? octstr_get_cstr(myhostname) : "none"); - http_header_remove_all(headers, "X-Mms-Message-Type"); - http_header_add(newhdrs, "X-Mms-Message-Type", "MM4_forward.REQ"); + octstr_destroy(xsender); + } http_header_combine(headers, newhdrs); mime_replace_headers(m, headers); + done: http_destroy_headers(headers); http_destroy_headers(newhdrs); - ret = send2email(to, from, subject, msgid, m, append_hostname, error, sendmail_cmd, myhostname); + if (ret == 0) + ret = send2email(to, + from, subject, msgid, m, mm4 == 0, error, sendmail_cmd, myhostname); mime_entity_destroy(m); return ret; @@ -1062,9 +1144,15 @@ void strip_boundary_element(List *headers, char *s) { Octstr *ctype = NULL, *params = NULL; Octstr *value; + int n; gw_assert(headers); - get_content_type(headers, &ctype, ¶ms); + + if ((n = get_content_type(headers, &ctype, ¶ms)) < 0) { + if (ctype) + octstr_destroy(ctype); + ctype = NULL; /* no ctype found, so do not replace it! */ + } if (s) {/* we are replacing the content type as well as stripping */ if (ctype) @@ -1072,7 +1160,7 @@ void strip_boundary_element(List *headers, char *s) ctype = octstr_create(s); } - if (params) { + if (params && ctype) { List *h = get_value_parameters(params); Octstr *ps; http_header_remove_all(h,"boundary"); /* We don't need the boundary param if it is there. */ @@ -1085,10 +1173,12 @@ void strip_boundary_element(List *headers, char *s) http_destroy_headers(h); } else value = ctype; - - http_header_remove_all(headers, "Content-Type"); - http_header_add(headers, "Content-Type", octstr_get_cstr(value)); - if (ctype != value) + if (value) { + http_header_remove_all(headers, "Content-Type"); + http_header_add(headers, "Content-Type", octstr_get_cstr(value)); + } + if (ctype != value && ctype != NULL) octstr_destroy(ctype); - octstr_destroy(value); + if (value) + octstr_destroy(value); } diff --git a/mbuni/mmlib/mms_util.h b/mbuni/mmlib/mms_util.h index ec54efd..38f9db3 100644 --- a/mbuni/mmlib/mms_util.h +++ b/mbuni/mmlib/mms_util.h @@ -23,12 +23,18 @@ #include "mms_cfg.h" #include "mms_mmbox.h" +/* supported 3GPP MMS version */ +#define MMS_3GPP_VERSION "5.5.0" + /* Send errors */ #define MMS_SEND_OK 0 +#define MMS_SEND_QUEUED 1 #define MMS_SEND_ERROR_TRANSIENT -1 #define MMS_SEND_ERROR_FATAL -2 -#define SEND_ERROR_STR(e) ((e) == MMS_SEND_OK ? "Sent" : (e) == MMS_SEND_ERROR_TRANSIENT ? "Retry later" : "Failed") +#define SEND_ERROR_STR(e) ((e) == MMS_SEND_OK ? "Sent" : \ + (e) == MMS_SEND_ERROR_TRANSIENT ? "Retry later" : \ + ((e) == MMS_SEND_QUEUED ? "Queued" : "Failed")) /* Useful headers. */ #define XMSISDN_HEADER "X-WAP-Network-Client-MSISDN" #define XIP_HEADER "X-WAP-Network-Client-IP" @@ -88,7 +94,14 @@ int mms_sendtoemail(Octstr *from, Octstr *to, MmsMsg *msg, int dlr, Octstr **error, char *sendmail_cmd, Octstr *myhostname, int trans_msg, - int trans_smil, char *txt, char *html, int append_hostname); + int trans_smil, char *txt, char *html, int mm4, + char *transid); + +/* Send directly to email. */ +int mm_send_to_email(Octstr *to, Octstr *from, Octstr *subject, + Octstr *msgid, + MIMEEntity *m, int append_hostname, Octstr **error, + char *sendmail_cmd, Octstr *myhostname); /* log to access log. */ void mms_log(char *logmsg, Octstr *from, List *to, diff --git a/mbuni/mmsc/mmsc_cfg.c b/mbuni/mmsc/mmsc_cfg.c index 69328c1..d53f256 100644 --- a/mbuni/mmsc/mmsc_cfg.c +++ b/mbuni/mmsc/mmsc_cfg.c @@ -92,15 +92,17 @@ MmscSettings *mms_load_mmsc_settings(mCfg *cfg, List **proxyrelays) mms_load_core_settings(cgrp); + m->hostname = _mms_cfg_getx(grp, octstr_imm("hostname")); + if (proxyrelays) - *proxyrelays = mms_proxy_relays(cfg); + *proxyrelays = mms_proxy_relays(cfg, m->hostname); if (mms_cfg_get_int(grp, octstr_imm("max-send-threads"), &m->maxthreads) == -1) m->maxthreads = 10; m->unified_prefix = _mms_cfg_getx(grp, octstr_imm("unified-prefix")); m->local_prefix = _mms_cfg_getx(grp, octstr_imm("local-prefixes")); - m->hostname = _mms_cfg_getx(grp, octstr_imm("hostname")); + if (m->hostname == NULL || octstr_len(m->hostname) == 0) m->hostname = octstr_create("localhost"); @@ -122,8 +124,6 @@ MmscSettings *mms_load_mmsc_settings(mCfg *cfg, List **proxyrelays) m->global_queuedir = octstr_format("%S/global", qdir); m->mm1_queuedir = octstr_format("%S/mm1", qdir); - m->mm4_queuedir = octstr_format("%S/mm4", qdir); - if (mms_init_queuedir(m->mm1_queuedir) < 0) panic(0, "Failed to initialise local queue directory: %s - %s!", @@ -131,9 +131,6 @@ MmscSettings *mms_load_mmsc_settings(mCfg *cfg, List **proxyrelays) else if (mms_init_queuedir(m->global_queuedir) < 0) panic(0, "Failed to initialise global queue directory: %s - %s!", octstr_get_cstr(m->global_queuedir), strerror(errno)); - else if (mms_init_queuedir(m->mm4_queuedir) < 0) - panic(0, "Failed to initialise global queue directory: %s - %s!", - octstr_get_cstr(m->mm4_queuedir), strerror(errno)); m->mmbox_rootdir = octstr_format("%S/mmbox", qdir); @@ -336,7 +333,7 @@ MmscSettings *mms_load_mmsc_settings(mCfg *cfg, List **proxyrelays) return m; } -List *mms_proxy_relays(mCfg *cfg) +List *mms_proxy_relays(mCfg *cfg, Octstr *myhostname) { List *gl = mms_cfg_get_multi(cfg, octstr_imm("mmsproxy")); int i, n; @@ -349,8 +346,13 @@ List *mms_proxy_relays(mCfg *cfg) m->host = _mms_cfg_getx(grp, octstr_imm("host")); m->name = _mms_cfg_getx(grp, octstr_imm("name")); m->allowed_prefix = _mms_cfg_getx(grp, octstr_imm("allowed-prefix")); - m->denied_prefix = _mms_cfg_getx(grp, octstr_imm("denied-prefix")); + m->denied_prefix = _mms_cfg_getx(grp, octstr_imm("denied-prefix")); + if (mms_cfg_get_bool(grp, octstr_imm("confirmed-delivery"), &m->confirmed_mm4) < 0) + m->confirmed_mm4 = 1; + if (octstr_compare(m->host, myhostname) == 0) + warning(0, "MMSC Config: Found MM4 Proxy %s with same hostname as local host!", + octstr_get_cstr(m->name)); gwlist_append(l, m); } diff --git a/mbuni/mmsc/mmsc_cfg.h b/mbuni/mmsc/mmsc_cfg.h index ce4ffe6..9830602 100644 --- a/mbuni/mmsc/mmsc_cfg.h +++ b/mbuni/mmsc/mmsc_cfg.h @@ -22,6 +22,7 @@ typedef struct MmsProxyRelay { Octstr *name; Octstr *allowed_prefix; Octstr *denied_prefix; + int confirmed_mm4; } MmsProxyRelay; typedef struct MmsVasp { @@ -37,7 +38,7 @@ typedef struct MmscSettings { Octstr *name, *hostname, *host_alias; Octstr *unified_prefix, *local_prefix; Octstr *sendmail; - Octstr *global_queuedir, *mm1_queuedir, *mm4_queuedir; + Octstr *global_queuedir, *mm1_queuedir; Octstr *mmbox_rootdir; Octstr *ua_profile_cache_dir; @@ -100,7 +101,7 @@ typedef struct MmscSettings { MmscSettings *mms_load_mmsc_settings(mCfg *cfg, List **proxyrelays); /* Returns list of MmsProxyRelay */ -extern List *mms_proxy_relays(mCfg *cfg); +extern List *mms_proxy_relays(mCfg *cfg, Octstr *myhostname); extern Octstr *mms_makefetchurl(char *qf, Octstr *token, int loc, Octstr *to, diff --git a/mbuni/mmsc/mmsfromemail.c b/mbuni/mmsc/mmsfromemail.c index b4f2395..fd89179 100644 --- a/mbuni/mmsc/mmsfromemail.c +++ b/mbuni/mmsc/mmsfromemail.c @@ -22,12 +22,31 @@ static Octstr *xto; static Octstr *xproxy; enum {TPLMN, TEMAIL, TOTHER} ttype; +/* MM4 message types. */ +enum {MM4_FORWARD_REQ = 0, MM4_FORWARD_RES, MM4_READ_REPLY_REPORT_REQ, + MM4_READ_REPLY_REPORT_RES, MM4_DELIVERY_REPORT_REQ, MM4_DELIVERY_REPORT_RES}; +static struct { + char *mm4str; + int mm1_type; +} mm4_types[] = { + {"MM4_forward.REQ", MMS_MSGTYPE_SEND_REQ}, + {"MM4_forward.RES",-1}, + {"MM4_read_reply_report.REQ", MMS_MSGTYPE_READ_REC_IND}, + {"MM4_read_reply_report.RES",-1}, + {"MM4_delivery_report.REQ",MMS_MSGTYPE_DELIVERY_IND}, + {"MM4_delivery_report.RES",-1}, + {NULL} +}; +/* above indexed by types! */ static int find_own(int i, int argc, char *argv[]); static void fixup_recipient(void); static void fixup_sender(void); +static void send_mm4_res(int mtype, Octstr *to, Octstr *sender, Octstr *transid, char *status, Octstr *msgid); + + static mCfg *cfg; static List *proxyrelays; int main(int argc, char *argv[]) @@ -38,14 +57,17 @@ int main(int argc, char *argv[]) MIMEEntity *mm; MmsMsg *msg; - Octstr *email; + Octstr *email, *me, *rstatus; Octstr *home_mmsc = NULL; List *headers; + Octstr *mm4_type = NULL, *transid, *ack, *msgid, *orig_sys; + Octstr *newmsgid = NULL; + + int mtype = -1, mm1_type = -1; + char *err = NULL; mms_lib_init(); - srandom(time(NULL)); - cfidx = get_and_set_debugs(argc, argv, find_own); if (argv[cfidx] == NULL) @@ -71,8 +93,10 @@ int main(int argc, char *argv[]) if (!settings) panic(0, "No global MMSC configuration!"); - if (!xto || !xfrom) - panic(0, "usage: %s -f from -t to!", argv[0]); + if (!xto || !xfrom) { + error(0, "usage: %s -f from -t to!", argv[0]); + return -1; + } /* normalize recipient address, then if phone number, * check whether we are allowed to process. @@ -120,33 +144,93 @@ int main(int argc, char *argv[]) http_header_remove_all(headers, "Received"); http_header_remove_all(headers, "X-MimeOLE"); http_header_remove_all(headers, "X-Mailer"); + + /* Look for MM4 headers... */ + mm4_type = http_header_value(headers, octstr_imm("X-Mms-Message-Type")); + ack = http_header_value(headers, octstr_imm("X-Mms-Ack-Request")); + rstatus = http_header_value(headers, octstr_imm("X-Mms-Request-Status-Code")); + + if ((transid = http_header_value(headers, octstr_imm("X-Mms-Transaction-ID"))) == NULL) + transid = octstr_create("001"); + /* get originator system. */ + if ((orig_sys = http_header_value(headers, octstr_imm("X-Mms-Originator-System"))) == NULL) + orig_sys = http_header_value(headers, octstr_imm("Sender")); + + if (xproxy == NULL && orig_sys != NULL) { /* Copy proxy address from originator system. */ + int i = octstr_search_char(orig_sys, '@', 0); + if (i >= 0) + xproxy = octstr_copy(orig_sys, i+1, octstr_len(orig_sys)); + } + + if ((msgid = http_header_value(headers, octstr_imm("X-Mms-Message-ID"))) == NULL) + msgid = http_header_value(headers, octstr_imm("Message-ID")); + + if (msgid) + octstr_strip_nonalphanums(msgid); + if (transid) + octstr_strip_nonalphanums(transid); + + /* ... and remove non-essential ones */ + http_header_remove_all(headers, "X-Mms-3GPP-MMS-Version"); + http_header_remove_all(headers, "MIME-Version"); + http_header_remove_all(headers, "X-Mms-Message-ID"); + http_header_remove_all(headers, "Message-ID"); + http_header_remove_all(headers, "X-Mms-Ack-Request"); + http_header_remove_all(headers, "X-Mms-Originator-System"); + http_header_remove_all(headers, "Sender"); + + /* msgid was there, put it back in proper form. */ + if (msgid) + http_header_add(headers, "Message-ID", octstr_get_cstr(msgid)); + + if (mm4_type) { + unsigned char *x = NULL; + int i; + + http_header_remove_all(headers, "X-Mms-Message-Type"); + for (i = 0; mm4_types[i].mm4str; i++) + if (octstr_str_case_compare(mm4_type, mm4_types[i].mm4str) == 0) { + mtype = i; + mm1_type = mm4_types[i].mm1_type; + x = mms_message_type_to_cstr(mm1_type); + break; + } + if (x) + http_header_add(headers, "X-Mms-Message-Type", (char *)x); + + if (orig_sys == NULL) /* Make it up! */ + orig_sys = octstr_format("system-user@%S", xproxy ? xproxy : octstr_imm("unknown")); + } else { /* else assume a normal send message. */ + http_header_add(headers, "X-Mms-Message-Type", "m-send-req"); + mm1_type = MMS_MSGTYPE_SEND_REQ; + mtype = MM4_FORWARD_REQ; + } + mime_replace_headers(mm, headers); http_destroy_headers(headers); - /* Now convert from mime to MMS message. */ - msg = mms_frommime(mm); - mime_entity_destroy(mm); + /* Now convert from mime to MMS message, if we should */ + if (mm1_type >= 0) { + if ((msg = mms_frommime(mm)) == NULL) { + error(0, "Unable to create MM!"); + mms_lib_shutdown(); + return -1; + } + } else + msg = NULL; + mime_entity_destroy(mm); + me = octstr_format("system-user@%S", settings->hostname); - if (!msg) { - error(0, "Unable to create MM!"); - mms_lib_shutdown(); - return -1; - } - - switch(mms_messagetype(msg)) { - case MMS_MSGTYPE_SEND_REQ: - if (ttype != TPLMN) + switch(mtype) { + case MM4_FORWARD_REQ: + if (ttype != TPLMN) { + err = "Error-service-denied"; error(0, "Not allowed to send to non-phone recipient, to=%s!", octstr_get_cstr(xto)); - - else { + } else { List *lto = gwlist_create(); Octstr *qf; - Octstr *msgid = mms_get_header_value(msg, octstr_imm("Message-ID")); - Octstr *transid = mms_get_header_value(msg, octstr_imm("X-Mms-Transaction-ID")); - Octstr *dreport = mms_get_header_value(msg, - octstr_imm("X-Mms-Delivery-Report")); - char *err; - Octstr *rto; + Octstr *dreport = mms_get_header_value(msg, octstr_imm("X-Mms-Delivery-Report")); + int dlr; octstr_format_append(xto, "/TYPE=PLMN"); @@ -167,8 +251,10 @@ int main(int argc, char *argv[]) octstr_get_cstr(settings->global_queuedir), settings->host_alias); if (qf) { - - info(0, "Email2MMS Queued message to %s from %s (via %s) => %s", + newmsgid = mms_maketransid(octstr_get_cstr(qf), + settings->host_alias); + info(0, "%s Queued message to %s from %s (via %s) => %s", + mm4_type ? "MM4 Incoming" : "Email2MMS", octstr_get_cstr(xto), octstr_get_cstr(xfrom), xproxy ? octstr_get_cstr(xproxy) : "(None)", octstr_get_cstr(qf)); octstr_destroy(qf); @@ -176,156 +262,181 @@ int main(int argc, char *argv[]) /* Queue our response to the chap. */ err = "Ok"; } else - err = "Error-transient-failure"; - if (xproxy) { - MmsMsg *mresp; - List *xlto; - mresp = mms_sendconf(err, octstr_get_cstr(msgid), - transid ? octstr_get_cstr(transid) : "001", - 0,MS_1_1); - - rto = octstr_format("system-user@%S", xproxy); - xlto = gwlist_create(); - gwlist_append(xlto, rto); - - qf = mms_queue_add(settings->system_user, xlto, NULL, - xproxy, NULL, - 0, time(NULL) + settings->default_msgexpiry, - mresp, NULL, - NULL, NULL, - NULL, NULL, - NULL, - 0, - octstr_get_cstr(settings->global_queuedir), - settings->host_alias); - - gwlist_destroy(xlto, (gwlist_item_destructor_t *)octstr_destroy); - mms_destroy(mresp); - octstr_destroy(qf); - } - + err = "Error-network-problem"; mms_log("Received", xfrom, lto, - -1, msgid, NULL, xproxy, xproxy ? "MM4" : "MM3", NULL,NULL); + -1, msgid, NULL, xproxy, mm4_type ? "MM4" : "MM3", NULL,NULL); gwlist_destroy(lto,NULL); - octstr_destroy(transid); - octstr_destroy(msgid); if (dreport) octstr_destroy(dreport); } break; - - case MMS_MSGTYPE_SEND_CONF: + case MM4_DELIVERY_REPORT_REQ: + if (ttype != TPLMN) { /* We only send to phones from this interface */ + error(0, "Not allowed to send to %s!", octstr_get_cstr(xto)); + err = "Error-service-denied"; + } else { + List *lto = gwlist_create(); + Octstr *qf; + + + octstr_format_append(xto, "/TYPE=PLMN"); + gwlist_append(lto, xto); + qf = mms_queue_add(xfrom, lto, NULL, + xproxy, NULL, + 0, time(NULL) + settings->default_msgexpiry, msg, NULL, + NULL, NULL, + NULL, NULL, + NULL, + 0, + octstr_get_cstr(settings->global_queuedir), + settings->host_alias); + gwlist_destroy(lto, NULL); + if (qf) { + info(0, "MM4 Queued DLR from proxy %s to %s from %s => %s", + octstr_get_cstr(xproxy), octstr_get_cstr(xto), octstr_get_cstr(xfrom), + octstr_get_cstr(qf)); + octstr_destroy(qf); + err = "Ok"; + } else + err = "Error-network-problem"; + newmsgid = msgid ? octstr_duplicate(msgid) : NULL; /* report old msg id */ + } + break; + + case MM4_READ_REPLY_REPORT_REQ: + if (ttype != TPLMN) { /* We only send to phones from this interface */ + error(0, "Not allowed to send to %s!", octstr_get_cstr(xto)); + err = "Error-service-denied"; + } else { + List *lto = gwlist_create(); + Octstr *qf; + + octstr_format_append(xto, "/TYPE=PLMN"); + gwlist_append(lto, xto); + qf = mms_queue_add(xfrom, lto, NULL, + xproxy, NULL, + 0, time(NULL) + settings->default_msgexpiry, msg, NULL, + NULL, NULL, + NULL, NULL, + NULL, + 0, + octstr_get_cstr(settings->global_queuedir), + settings->host_alias); + gwlist_destroy(lto, NULL); + if (qf) { + info(0, "MM4 Queued read report from proxy %s to %s from %s => %s", + octstr_get_cstr(xproxy), octstr_get_cstr(xto), octstr_get_cstr(xfrom), + octstr_get_cstr(qf)); + octstr_destroy(qf); + err = "Ok"; + } else + err = "Error-network-problem"; + } + + case MM4_FORWARD_RES: + case MM4_READ_REPLY_REPORT_RES: + case MM4_DELIVERY_REPORT_RES: /* remove corresponding queue entry. */ { - Octstr *transid = mms_get_header_value(msg, octstr_imm("X-Mms-Transaction-ID")); - Octstr *qf = mms_getqf_fromtransid(transid); + Octstr *qf, *o_to; + int i; - octstr_destroy(transid); + /* Pull the number out of the fake transaction ID */ + if ((i = octstr_search_char(transid, '-',0)) > 0) { + o_to = octstr_copy(transid, 0, i); + octstr_delete(transid, 0, i+1); + } else + o_to = NULL; + qf = mms_getqf_fromtransid(transid); if (qf) { MmsEnvelope *e = mms_queue_readenvelope(octstr_get_cstr(qf), - octstr_get_cstr(settings->mm4_queuedir), + octstr_get_cstr(settings->global_queuedir), 1); if (!e) - warning(0, "Received confirm MMS but cannot find message %s [%s] in queue!", + warning(0, "MM4 Received %s from %s but cannot load queue entry %s [%s] in queue!", + mm4_types[mtype].mm4str, + octstr_get_cstr(xproxy), octstr_get_cstr(transid), + octstr_get_cstr(qf)); else { MmsEnvelopeTo *t; int i, n; for (i = 0, n = gwlist_len(e->to); ito, i)) != NULL) + if ((t = gwlist_get(e->to, i)) != NULL && + (o_to == NULL || octstr_case_compare(o_to, t->rcpt) == 0)) t->process = 0; /* Should make it go away. */ + + /* write CDR if it is a forward confirmation */ + if (mtype == MM4_FORWARD_RES && + rstatus && octstr_str_case_compare(rstatus, "Ok") == 0) { + MmsCdrStruct _cdr, *cdr = &_cdr; + + cdr->module_data = settings->mms_bill_module_data; + cdr->sdate = e->created; + strncpy(cdr->from, octstr_get_cstr(e->from), sizeof cdr->from); + strncpy(cdr->to, o_to ? octstr_get_cstr(o_to) : "", sizeof cdr->to); + strncpy(cdr->msgid, e->msgId ? octstr_get_cstr(e->msgId) : "", sizeof cdr->msgid); + strncpy(cdr->vaspid, e->vaspid ? octstr_get_cstr(e->vaspid) : "", sizeof cdr->vaspid); + cdr->msg_size = e->msize; + + settings->mms_billfuncs->mms_logcdr(cdr); + } mms_queue_update(e); - info(0, "Email2MMS received send conf from proxy %s to %s from %s => %s", - octstr_get_cstr(xproxy), octstr_get_cstr(xto), + + info(0, "MM4 received %s from proxy %s to %s from %s => %s, status: %s", + mm4_types[mtype].mm4str, + octstr_get_cstr(xproxy), o_to ? octstr_get_cstr(o_to) : octstr_get_cstr(xto), octstr_get_cstr(xfrom), - octstr_get_cstr(qf)); + octstr_get_cstr(qf), + rstatus ? octstr_get_cstr(rstatus) : ""); } } else - warning(0, "Received confirm MMS but cannot find message %s in queue!", + warning(0, "Received %s but cannot find message %s in queue!", + mm4_types[mtype].mm4str, octstr_get_cstr(transid)); + + if (o_to) + octstr_destroy(o_to); + } - break; - case MMS_MSGTYPE_DELIVERY_IND: - if (ttype != TPLMN) /* We only send to phones from this interface */ - error(0, "Not allowed to send to %s!", octstr_get_cstr(xto)); - else { - List *lto = gwlist_create(); - Octstr *qf; - - - octstr_format_append(xto, "/TYPE=PLMN"); - gwlist_append(lto, xto); - qf = mms_queue_add(xfrom, lto, NULL, - xproxy, NULL, - 0, time(NULL) + settings->default_msgexpiry, msg, NULL, - NULL, NULL, - NULL, NULL, - NULL, - 0, - octstr_get_cstr(settings->global_queuedir), - settings->host_alias); - gwlist_destroy(lto, NULL); - if (qf) { - info(0, "Email2MMS Queued DLR from proxy %s to %s from %s => %s", - octstr_get_cstr(xproxy), octstr_get_cstr(xto), octstr_get_cstr(xfrom), - octstr_get_cstr(qf)); - - octstr_destroy(qf); - } - - gwlist_destroy(lto, NULL); - } - break; - - case MMS_MSGTYPE_READ_REC_IND: - - mms_convert_readrec2readorig(msg); - - /* Fall through. */ - case MMS_MSGTYPE_READ_ORIG_IND: - if (ttype != TPLMN) /* We only send to phones from this interface */ - error(0, "Not allowed to send to %s!", octstr_get_cstr(xto)); - else { - List *lto = gwlist_create(); - Octstr *qf; - - octstr_format_append(xto, "/TYPE=PLMN"); - gwlist_append(lto, xto); - qf = mms_queue_add(xfrom, lto, NULL, - xproxy, NULL, - 0, time(NULL) + settings->default_msgexpiry, msg, NULL, - NULL, NULL, - NULL, NULL, - NULL, - 0, - octstr_get_cstr(settings->global_queuedir), - settings->host_alias); - gwlist_destroy(lto, NULL); - if (qf) { - info(0, "Email2MMS Queued read report from proxy %s to %s from %s => %s", - octstr_get_cstr(xproxy), octstr_get_cstr(xto), octstr_get_cstr(xfrom), - octstr_get_cstr(qf)); - - octstr_destroy(qf); - } - - - gwlist_destroy(lto, NULL); - } + break; default: - { - int x = mms_messagetype(msg); - warning(0, "Unexpected message type: %d=>%s", - x, - mms_message_type_to_cstr(x)); + warning(0, "Unexpected message type: %s", + mm4_type ? octstr_get_cstr(mm4_type) : "not given!"); break; } - } + /* respond to the sender as necessary. */ + if (mm4_type && + err && + ack && octstr_str_case_compare(ack, "Yes") == 0) + send_mm4_res(mtype+1, orig_sys, me, transid, err, newmsgid); + + if (mm4_type) + octstr_destroy(mm4_type); + if (transid) + octstr_destroy(transid); + if (orig_sys) + octstr_destroy(orig_sys); + if (msgid) + octstr_destroy(msgid); + if (newmsgid) + octstr_destroy(newmsgid); + if (rstatus) + octstr_destroy(rstatus); + + if (xto) + octstr_destroy(xto); + if (xfrom) + octstr_destroy(xfrom); + if (xproxy) + octstr_destroy(xproxy); + octstr_destroy(me); + mms_destroy(msg); mms_lib_shutdown(); @@ -365,11 +476,12 @@ static void fixup_recipient(void) Octstr *typ = NULL; - if (!xto) xto = octstr_imm(""); - i = octstr_search_char(xto, '@', 0); + if (!xto) return; + + i = octstr_search_char(xto, '@', 0); /* Remove '@' */ if (i>0) octstr_delete(xto, i, octstr_len(xto)); - + i = octstr_search(xto, octstr_imm("/TYPE="), 0); if (i > 0) { typ = octstr_copy(xto, i+1, octstr_len(xto)); @@ -383,25 +495,60 @@ static void fixup_recipient(void) } else { /* For now everything else is email. */ ttype = TEMAIL; } - octstr_destroy(typ); + if (typ) + octstr_destroy(typ); } static void fixup_sender(void) { int i; - - if (!xfrom) xfrom = octstr_imm(""); - i = octstr_search_char(xfrom, '@', 0); - if (i>0) - return; + /* Find the TYPE=xxx element. If it is there, it is a number. Strip the @ */ + + if (!xfrom) return; i = octstr_search(xfrom, octstr_imm("/TYPE="), 0); - if (i > 0) - return; - - if (isphonenum(xfrom)) - octstr_append(xfrom, octstr_imm("/TYPE=PLMN")); - else - octstr_append(xfrom, octstr_imm("@unknown")); + if (i>0) { + int j = octstr_search_char(xfrom, '@', 0); + if (j > i) { /* we have @, remove it */ + if (xproxy == NULL) + xproxy = octstr_copy(xfrom, j+1, octstr_len(xfrom)); + octstr_delete(xfrom, j, octstr_len(xfrom)); + } + } else if (isphonenum(xfrom)) /* Add the TYPE element if missing. */ + octstr_append(xfrom, octstr_imm("/TYPE=PLMN")); + else { + i = octstr_search_char(xfrom, '@', 0); + if (i<0) + octstr_format_append(xfrom, "@unknown"); + else if (xproxy == NULL) + xproxy = octstr_copy(xfrom, i+1, octstr_len(xfrom)); + } +} + +static void send_mm4_res(int mtype, Octstr *to, Octstr *sender, Octstr *transid, char *status, Octstr *msgid) +{ + List *h = http_create_empty_headers(); + MIMEEntity *m = mime_entity_create(); + Octstr *err = NULL; + /* Make headers */ + http_header_add(h, "X-Mms-3GPP-MMS-Version", MMS_3GPP_VERSION); + http_header_add(h, "X-Mms-Transaction-ID", octstr_get_cstr(transid)); + http_header_add(h, "X-Mms-Message-Type", mm4_types[mtype].mm4str); + if (msgid) + http_header_add(h, "X-Mms-Message-ID", octstr_get_cstr(msgid)); + http_header_add(h, "X-Mms-Request-Status-Code", status); + http_header_add(h, "Sender", octstr_get_cstr(sender)); + http_header_add(h, "To", octstr_get_cstr(to)); + + mime_replace_headers(m, h); + http_destroy_headers(h); + + mm_send_to_email(to, sender, octstr_imm(""), msgid, m, 0, &err, octstr_get_cstr(settings->sendmail), + settings->hostname); + if (err) { + warning(0, "MM4 send.RES reported: %s!", octstr_get_cstr(err)); + octstr_destroy(err); + } + mime_entity_destroy(m); } diff --git a/mbuni/mmsc/mmsglobalsender.c b/mbuni/mmsc/mmsglobalsender.c index bbc6dd6..df0debb 100644 --- a/mbuni/mmsc/mmsglobalsender.c +++ b/mbuni/mmsc/mmsglobalsender.c @@ -15,15 +15,12 @@ #define NMAX 256 static char mobile_qdir[NMAX]; -static char mm4_qdir[NMAX]; static char sendmail_cmd[NMAX]; /* Set the queue directory for messages going to mobile. */ static int mms_setmobile_queuedir(char *mqdir); -/* Set the queue directory for messages going to remote proxies. */ -static int mms_setmm4_queuedir(char *mqdir); /* Send command for sending mail. It will be called as with * headers and message on stdin. @@ -47,7 +44,9 @@ static int mms_sendtomobile(Octstr *from, Octstr *to, */ static int mms_sendtoproxy(Octstr *from, Octstr *to, Octstr *subject, Octstr *proxy, - Octstr *msgid, time_t expires, MmsMsg *m, int dlr, Octstr **error); + char *transid, + Octstr *msgid, time_t expires, MmsMsg *msg, + int dlr, Octstr **error); static int mms_sendtovasp(MmsVasp *vasp, Octstr *from, Octstr *to, Octstr *msgId, MmsMsg *m, Octstr **error); @@ -147,26 +146,34 @@ static int sendMsg(MmsEnvelope *e) */ if (octstr_search_char(to->rcpt, '@', 0) > 0) { + Octstr *pfrom; + if (octstr_search_char(e->from, '@', 0) < 0) + pfrom = octstr_format("%S@%S", e->from, settings->hostname); + else + pfrom = e->from; + if (settings->mms2email) res = mms_sendtovasp(settings->mms2email, e->from, to->rcpt, e->msgId, msg, &err); else - res = mms_sendtoemail(e->from, to->rcpt, + res = mms_sendtoemail(pfrom, to->rcpt, e->subject ? e->subject : settings->mms_email_subject, - e->msgId, msg, e->dlr, &err, sendmail_cmd, + e->msgId, msg, 0, &err, sendmail_cmd, settings->hostname, 1, 1, octstr_get_cstr(settings->mms_email_txt), - octstr_get_cstr(settings->mms_email_html), 1); + octstr_get_cstr(settings->mms_email_html), 0, e->xqfname); + if (res == MMS_SEND_QUEUED) + res = MMS_SEND_OK; /* queued to email treated same as sent. + * XXX - this means DLR requests for emailed messages not supported! + */ if (res == MMS_SEND_OK) mms_log2("Sent", e->from, to->rcpt, -1, e->msgId, NULL, NULL, "MM3", NULL,NULL); - } else if (e->viaproxy && octstr_len(e->viaproxy) > 0) - res = mms_sendtoproxy(e->from, - to->rcpt, e->subject, e->viaproxy, - e->msgId, e->expiryt, msg, e->dlr, &err); - else { + if (pfrom != e->from) + octstr_destroy(pfrom); + } else { int j = octstr_case_search(to->rcpt, octstr_imm("/TYPE=PLMN"), 0); int k = octstr_case_search(to->rcpt, octstr_imm("/TYPE=IPv"), 0); int len = octstr_len(to->rcpt); @@ -227,7 +234,7 @@ static int sendMsg(MmsEnvelope *e) settings, proxyrelays))) { info(0, "mmsc for \"%s\" resolved to: \"%s\"", octstr_get_cstr(phonenum), octstr_get_cstr(mmsc)); - + /* If resolved to my hostname, then this is local. */ if (octstr_compare(mmsc, settings->hostname) == 0) { if (settings->mms2mobile && e->msgtype == MMS_MSGTYPE_SEND_REQ) { /* Send a copy to this VASP. */ @@ -251,16 +258,20 @@ static int sendMsg(MmsEnvelope *e) e->msgId, e->expiryt, msg, e->dlr, &err); sent = 1; - } else if (proxyrelays && gwlist_len(proxyrelays) > 0) /* Step through proxies. */ + } else if (proxyrelays && gwlist_len(proxyrelays) > 0) + /* else, step through proxies, look for one that matches. */ for (j = 0, m = gwlist_len(proxyrelays); jhost, mmsc)) { + Octstr *xtransid = mms_maketransid(e->xqfname, settings->host_alias); res = mms_sendtoproxy(e->from, to->rcpt, - e->subject, mp->host, + e->subject, mp->host, + octstr_get_cstr(xtransid), e->msgId, e->expiryt, msg, - e->dlr, &err); + mp->confirmed_mm4, &err); sent = 1; + octstr_destroy(xtransid); break; } } @@ -282,11 +293,16 @@ static int sendMsg(MmsEnvelope *e) if (e->dlr) { Octstr *qfs; - MmsMsg *m = mms_deliveryreport(e->msgId, to->rcpt, tnow, - (e->expiryt != 0 && e->expiryt < tnow) ? - octstr_imm("Expired") : octstr_imm("Rejected")); - + char *mstatus; + if (res == MMS_SEND_QUEUED) + mstatus = "Forwarded"; + else if (e->expiryt != 0 && e->expiryt < tnow) + mstatus = "Expired"; + else + mstatus = "Rejected"; + MmsMsg *m = mms_deliveryreport(e->msgId, to->rcpt, tnow, octstr_imm(mstatus)); + List *l = gwlist_create(); gwlist_append(l, octstr_duplicate(e->from)); @@ -369,7 +385,6 @@ void mbuni_global_queue_runner(int *rstop) { mms_setmobile_queuedir(octstr_get_cstr(settings->mm1_queuedir)); - mms_setmm4_queuedir(octstr_get_cstr(settings->mm4_queuedir)); mms_setsendmail_cmd(octstr_get_cstr(settings->sendmail)); @@ -398,11 +413,6 @@ static int mms_setmobile_queuedir(char *mqdir) return 0; } -static int mms_setmm4_queuedir(char *mqdir) -{ - strncpy(mm4_qdir, mqdir, sizeof mm4_qdir); - return 0; -} static int mms_setsendmail_cmd(char *sendmail) { @@ -460,52 +470,50 @@ int mms_sendtomobile(Octstr *from, Octstr *to, * so we can handle delivery receipts and such. */ static int mms_sendtoproxy(Octstr *from, Octstr *to, - Octstr *subject, Octstr *proxy, - Octstr *msgid, time_t expires, MmsMsg *msg, int dlr, Octstr **error) + Octstr *subject, Octstr *proxy, + char *transid, + Octstr *msgid, time_t expires, MmsMsg *msg, + int dlr, Octstr **error) { - - Octstr *pto; + + Octstr *pto, *pfrom; int x = MMS_SEND_ERROR_FATAL; - + Octstr *xtransid; /* We make a fake transaction ID that includes 'to' field. */ + if (!to || octstr_search_char(to, '@', 0) >= 0) { *error = octstr_format("Bad recipient address sent to MM4 interface, addresss is %S!", to); return MMS_SEND_ERROR_FATAL; } - if (msg && - mms_messagetype(msg) == MMS_MSGTYPE_SEND_REQ) { /* Only queue these ones for future response. */ - List *l = gwlist_create(); - Octstr *ret; - gwlist_append(l, to); - ret = mms_queue_add(from, l, subject, NULL, proxy, 0, expires, msg,NULL, - NULL, NULL, - NULL, NULL, - NULL, - dlr, mm4_qdir, - settings->host_alias); - gwlist_destroy(l, NULL); - - if (ret == NULL) { - *error = octstr_format("MM4: Failed to queue message to %S for future tracking. ", to); - return MMS_SEND_ERROR_TRANSIENT; - } - octstr_destroy(ret); - } - if (msg) { - pto = octstr_format("%S@%S", to, proxy); - x = mms_sendtoemail(from, pto, - subject ? subject : settings->mms_email_subject, - msgid, msg, 0, - error, sendmail_cmd, - settings->hostname, 0, 0,NULL,NULL,0); - - mms_log2("Sent", from, pto, - -1, msgid, NULL, proxy, "MM4", NULL,NULL); - - octstr_destroy(pto); - } else + if (!msg) { *error = octstr_format("GlobalSend: Failed to send to %S, Message format is corrupt!", to); + return MMS_SEND_ERROR_FATAL; + } + + pto = octstr_format("%S@%S", to, proxy); + if (octstr_search_char(from, '@', 0) < 0) + pfrom = octstr_format("%S@%S", from, settings->hostname); + else + pfrom = from; + + xtransid = octstr_format("%S-%s", to,transid); + x = mms_sendtoemail(from, pto, + subject ? subject : settings->mms_email_subject, + msgid, msg, dlr, + error, sendmail_cmd, + settings->hostname, 0, 0,NULL,NULL,1, octstr_get_cstr(xtransid)); + octstr_destroy(xtransid); + + if (x == MMS_SEND_QUEUED && !dlr) /* No confirmed sending, and message was queued successfully... */ + x = MMS_SEND_OK; /* we assume fully sent! */ + + if (x >= 0) /* no error. */ + mms_log2(x == MMS_SEND_OK ? "Sent" : "Queued", from, pto, + -1, msgid, NULL, proxy, "MM4", NULL,NULL); + octstr_destroy(pto); + if (pfrom != from) + octstr_destroy(pfrom); return x; }