1
0
Fork 0

mmsbox now sends multiple recipients per transaction

This commit is contained in:
bagyenda 2010-12-09 10:36:29 +00:00
parent 18dd46568f
commit cdabed7443
9 changed files with 411 additions and 219 deletions

View File

@ -1,3 +1,5 @@
2010-12-09 P. A. Bagyenda <bagyenda@dsmagic.com>
* Changes to mmsbox to allow it send multiple recipients per MM7 transaction
2010-11-30 P. A. Bagyenda <bagyenda@dsmagic.com>
* Minor fix in RFC 2047 text handling
2010-11-29 P. A. Bagyenda <bagyenda@dsmagic.com>

View File

@ -2755,6 +2755,22 @@ string
</td>
</tr>
<tr>
<td valign=top >
<tt>max-recipients</tt>
</td>
<td valign=top >
Number
</td>
<td valign=top >
Maximum number of recipients per transaction for this MMSC
(ignored for custom MMSC type). This controls how many <tt>To</tt>
addresses are included in each send transaction. Default is
1. Note that failure of of the MMSC to accept any of the
recipients can result in the entire send request being retried.
</td>
</tr>
<tr>
<td valign=top >
<tt>reroute</tt>

View File

@ -194,6 +194,8 @@ MULTI_GROUP(mmsc,
OCTSTR(default-vasid)
OCTSTR(maximum-request-size)
OCTSTR(strip-domain)
OCTSTR(max-recipients)
)
MULTI_GROUP(mms-service,

View File

@ -529,7 +529,7 @@ static void addmmscname(Octstr *s, Octstr *myhostname)
}
static int send2email(Octstr *to, Octstr *from, Octstr *subject,
static int send2email(List *xto, Octstr *from, Octstr *subject,
Octstr *msgid,
MIMEEntity *m, int append_hostname, Octstr **error,
char *sendmail_cmd, Octstr *myhostname,
@ -543,8 +543,9 @@ static int send2email(Octstr *to, Octstr *from, Octstr *subject,
Octstr *cmd = octstr_create("");
List *headers = mime_entity_headers(m); /* we don't want the mime version header removed. */
Octstr *to = NULL;
fname[0] = 0;
/* Make to address */
if (append_hostname) { /* Add our hostname to all phone numbers. */
List *l = http_create_empty_headers();
@ -607,11 +608,7 @@ static int send2email(Octstr *to, Octstr *from, Octstr *subject,
s = mime_entity_to_octstr(m);
if (relay_host && relay_port > 0) {
List *lto = gwlist_create();
gwlist_append(lto, octstr_duplicate(to));
ret = smtp_send(octstr_get_cstr(relay_host), relay_port, from, lto, s);
gwlist_destroy(lto, (void *)octstr_destroy);
ret = smtp_send(octstr_get_cstr(relay_host), relay_port, from, xto, s);
goto done;
}
/*
@ -622,6 +619,7 @@ static int send2email(Octstr *to, Octstr *from, Octstr *subject,
* m - message id
*/
LINEARISE_STR_LIST(to,xto," ");
i = 0;
for (;;) {
Octstr *tmp;
@ -679,6 +677,7 @@ static int send2email(Octstr *to, Octstr *from, Octstr *subject,
i += 2;
}
if ((fd = mkstemp(fname)) < 0) {
*error = octstr_format("mkstemp: Failed to create temporary file: %s",
strerror(errno));
@ -721,6 +720,7 @@ done:
http_destroy_headers(headers);
octstr_destroy(cmd);
octstr_destroy(s);
octstr_destroy(to);
return ret;
}
@ -804,11 +804,14 @@ int mm_send_to_email(Octstr *to, Octstr *from, Octstr *subject,
char *sendmail_cmd, Octstr *myhostname,
Octstr *relay_host, int relay_port)
{
return send2email(to,from,subject,msgid,m,append_hostname,error,sendmail_cmd,myhostname, relay_host, relay_port);
List *lto = gwlist_create_ex(to);
int ret = send2email(lto,from,subject,msgid,m,append_hostname,error,sendmail_cmd,myhostname, relay_host, relay_port);
gwlist_destroy(lto, NULL);
return ret;
}
/* Send this message to email recipient. */
int mms_sendtoemail(Octstr *from, Octstr *to,
int mms_sendtoemail(Octstr *from, List *lto,
Octstr *subject, Octstr *msgid,
MmsMsg *msg, int dlr,
Octstr **error, char *sendmail_cmd,
@ -824,13 +827,18 @@ int mms_sendtoemail(Octstr *from, Octstr *to,
List *headers = NULL;
List *newhdrs = http_create_empty_headers();
int ret = 0, mtype;
Octstr *to;
gw_assert(msg);
mtype = mms_messagetype(msg);
/* Make 'to' header field in case we need it. */
LINEARISE_STR_LIST(to, lto, ", ");
if (!to ||
octstr_search_char(to, '@', 0) < 0) {
*error = octstr_format("Invalid email address %S!", to);
octstr_destroy(to);
return MMS_SEND_ERROR_FATAL;
}
@ -840,6 +848,7 @@ int mms_sendtoemail(Octstr *from, Octstr *to,
m == NULL) {
mms_warning(0, "send2email", NULL, "Failed to format message (msg=%s,ret=%d)",
m ? "OK" : "Not transformed",ret);
octstr_destroy(to);
return -ret;
}
@ -855,8 +864,10 @@ int mms_sendtoemail(Octstr *from, Octstr *to,
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));
#if 0 /* Should we reveal recipients ?? */
http_header_remove_all(headers, "To");
http_header_add(newhdrs, "To", octstr_get_cstr(to));
#endif
http_header_add(newhdrs, "Message-ID", msgid ? octstr_get_cstr(msgid) : "");
http_header_add(newhdrs, "MIME-Version", "1.0");
} else {
@ -947,9 +958,9 @@ int mms_sendtoemail(Octstr *from, Octstr *to,
done:
http_destroy_headers(headers);
http_destroy_headers(newhdrs);
octstr_destroy(to);
if (ret == 0)
ret = send2email(to,
ret = send2email(lto,
from, subject, msgid, m, mm4 == 0, error, sendmail_cmd, myhostname, relay_host, relay_port);
mime_entity_destroy(m);
@ -2535,3 +2546,16 @@ Octstr *pack_rfc2047_text(Octstr *in, int charset_mib_enum)
octstr_append_cstr(xs, "?=");
return xs;
}
List *gwlist_create_ex_real(const char *file, const char *func, int line,...)
{
va_list ap;
List *l = gwlist_create();
void *v;
va_start(ap, line);
while ((v = va_arg(ap, void *)) != NULL)
gwlist_append(l, v);
return l;
}

View File

@ -108,7 +108,7 @@ void base64_mimeparts(MIMEEntity *m, int all);
/* Send this message to email recipient: Returns 0 on success 1 or 2 on profile error
* (negate to get right one), -ve on some other error
*/
int mms_sendtoemail(Octstr *from, Octstr *to,
int mms_sendtoemail(Octstr *from, List *lto,
Octstr *subject, Octstr *msgid,
MmsMsg *msg, int dlr, Octstr **error,
char *sendmail_cmd, Octstr *myhostname,
@ -266,8 +266,24 @@ Octstr *parse_rfc2047_text(Octstr *in, int *mibenum);
#define QUEUERUN_INTERVAL 1*60 /* 1 minutes. */
#define DEFAULT_EXPIRE 3600*24*7 /* One week */
#define DEFAULT_SIMUL_RCPTS 10
#define HTTP_REPLACE_HEADER(hdr, hname, value) do { \
http_header_remove_all((hdr), (hname)); \
http_header_add((hdr), (hname), (value)); \
} while (0)
List *gwlist_create_ex_real(const char *file, const char *func, int line,...);
#define gwlist_create_ex(...) gwlist_create_ex_real(__FILE__,__FUNCTION__,__LINE__, __VA_ARGS__, NULL)
#define LINEARISE_STR_LIST(res,lst,sep) do { \
Octstr *__res; \
int __i; \
for (__res = octstr_create(""), __i = 0; __i < gwlist_len(lst); __i++) \
octstr_format_append(__res, "%s%S", \
octstr_len(__res) == 0 ? "" : (sep), gwlist_get((lst), __i)); \
(res) = __res; \
} while (0)
#endif

View File

@ -555,8 +555,7 @@ static int mm7eaif_receive(MmsBoxHTTPClientInfo *h)
strip_prefixes);
if ((hto = http_header_find_all(h->headers, "X-NOKIA-MMSC-To")) != NULL &&
gwlist_len(hto) > 0) { /* To address is in headers. */
if ((hto = http_header_find_all(h->headers, "X-NOKIA-MMSC-To")) != NULL && gwlist_len(hto) > 0) { /* To address is in headers. */
int i, n;
gwlist_destroy(to, (gwlist_item_destructor_t *)octstr_destroy);
@ -1137,7 +1136,7 @@ void mmsc_receive_func(MmscGrp *m)
* are observed!
* Don't remove from queue on fail, just leave it to expire.
*/
static Octstr *mm7soap_send(MmscGrp *mmc, Octstr *from, Octstr *to,
static Octstr *mm7soap_send(MmscGrp *mmc, Octstr *from, List *lto,
Octstr *transid,
Octstr *linkedid,
char *vasid,
@ -1151,12 +1150,14 @@ static Octstr *mm7soap_send(MmscGrp *mmc, Octstr *from, Octstr *to,
Octstr *ret = NULL;
int mtype = mms_messagetype(m);
int hstatus = HTTP_OK, tstatus = -1;
List *xto = gwlist_create();
MSoapMsg_t *mreq = NULL, *mresp = NULL;
List *rh = NULL, *ph = NULL;
Octstr *body = NULL, *rbody = NULL, *url = NULL;
Octstr *s, *r, *status_details = NULL;
char *xvasid = vasid ? vasid : (mmc->default_vasid ? octstr_get_cstr(mmc->default_vasid) : NULL);
Octstr *to;
LINEARISE_STR_LIST(to,lto,", ");
if (e == NULL || mmc == NULL)
goto done1;
@ -1165,10 +1166,9 @@ static Octstr *mm7soap_send(MmscGrp *mmc, Octstr *from, Octstr *to,
mms_message_type_to_cstr(mtype),
octstr_get_cstr(from), octstr_get_cstr(to));
gwlist_append(xto, to);
if ((mreq = mm7_mmsmsg_to_soap(m, (mmc == NULL || mmc->no_senderaddress == 0) ? from : NULL,
xto, transid,
lto, transid,
service_code,
linkedid,
1, octstr_get_cstr(mmc->vasp_id), xvasid, NULL, 0,/* UA N/A on this side. */
@ -1291,13 +1291,13 @@ done1:
http_destroy_headers(ph);
octstr_destroy(rbody);
octstr_destroy(url);
gwlist_destroy(xto, NULL);
octstr_destroy(to);
octstr_destroy(status_details);
return ret;
}
static Octstr *mm7eaif_send(MmscGrp *mmc, Octstr *from, Octstr *to,
static Octstr *mm7eaif_send(MmscGrp *mmc, Octstr *from, List *lto,
Octstr *transid,
char *vasid,
MmsEnvelope *e,
@ -1312,8 +1312,10 @@ static Octstr *mm7eaif_send(MmscGrp *mmc, Octstr *from, Octstr *to,
Octstr *body = NULL, *rbody = NULL, *xver = NULL;
char *msgtype;
MmsMsg *mresp = NULL;
int mresp_type = -1;
int mresp_type = -1, i;
Octstr *to;
LINEARISE_STR_LIST(to,lto,", ");
if (e == NULL || mmc == NULL)
goto done;
@ -1323,7 +1325,10 @@ static Octstr *mm7eaif_send(MmscGrp *mmc, Octstr *from, Octstr *to,
octstr_get_cstr(from), octstr_get_cstr(to));
http_header_remove_all(rh, "X-Mms-Allow-Adaptations");
for (i = 0; i < gwlist_len(lto); i++) {
Octstr *to = gwlist_get(lto, i);
http_header_add(rh, "X-NOKIA-MMSC-To", octstr_get_cstr(to));
}
http_header_add(rh, "X-NOKIA-MMSC-From", octstr_get_cstr(from));
xver = octstr_format(EAIF_VERSION, mmc->ver.major, mmc->ver.minor1);
@ -1347,7 +1352,9 @@ static Octstr *mm7eaif_send(MmscGrp *mmc, Octstr *from, Octstr *to,
/* Patch the message FROM and TO fields. */
mms_replace_header_value(m, "From", octstr_get_cstr(from));
#if 0
mms_replace_header_value(m, "To", octstr_get_cstr(to));
#endif
mms_replace_header_value(m,"X-Mms-Transaction-ID",
transid ? octstr_get_cstr(transid) : "000");
body = mms_tobinary(m);
@ -1411,7 +1418,7 @@ done:
octstr_destroy(body);
http_destroy_headers(ph);
octstr_destroy(rbody);
octstr_destroy(to);
octstr_destroy(resp);
octstr_destroy(xver);
return ret;
@ -1420,7 +1427,7 @@ done:
static Octstr *mm7http_send(MmscGrp *mmc,
MmsEnvelope *e,
Octstr *from, Octstr *to,
Octstr *from, List *lto,
MmsMsg *m, Octstr **error,
int *retry)
{
@ -1434,6 +1441,9 @@ static Octstr *mm7http_send(MmscGrp *mmc,
MIMEEntity *form_data = make_multipart_formdata();
Octstr *transid = e ? octstr_create(e->xqfname) : NULL;
int mm7type = mm7_msgtype_to_soaptype(mtype,1);
Octstr *to;
LINEARISE_STR_LIST(to,lto," ");
if (e == NULL || mmc == NULL)
goto done;
@ -1448,7 +1458,6 @@ static Octstr *mm7http_send(MmscGrp *mmc,
add_multipart_form_field(form_data, "from", "text/plain", NULL, from);
add_multipart_form_field(form_data, "mms", "application/vnd.wap.mms-message", NULL, mms);
mmsbox_event_cb(mmc->id, mm7type, 0, octstr_imm("1.0"), 0,
octstr_len(mms), e->attempts, from,
to, NULL, transid, hdrs, NULL);
@ -1490,14 +1499,15 @@ done:
octstr_destroy(mms);
mime_entity_destroy(form_data);
octstr_destroy(transid);
octstr_destroy(to);
return ret;
}
static int mms_sendtommsc(MmscGrp *mmc, MmsEnvelope *e, Octstr *to,
static int mms_sendtommsc(MmscGrp *mmc, MmsEnvelope *e,
List *lto, /* Of Octstr * */
Octstr *orig_transid,
MmsMsg *m,
Octstr **new_msgid,
List **errhdrs)
@ -1517,15 +1527,17 @@ static int mms_sendtommsc(MmscGrp *mmc, MmsEnvelope *e, Octstr *to,
mutex_lock(mmc->mutex); { /* Grab a lock on it. */
Octstr *err = NULL;
if (mmc->type == SOAP_MMSC)
id = mm7soap_send(mmc, from, to, transid, linkedid, vasid, service_code, e, m, &err, errhdrs, &retry);
id = mm7soap_send(mmc, from, lto, transid, linkedid, vasid, service_code, e, m, &err, errhdrs, &retry);
else if (mmc->type == EAIF_MMSC)
id = mm7eaif_send(mmc, from, to, transid, vasid, e, m, &err, &retry);
id = mm7eaif_send(mmc, from, lto, transid, vasid, e, m, &err, &retry);
else if (mmc->type == HTTP_MMSC)
id = mm7http_send(mmc,e, from, to, m, &err, &retry);
else if (mmc->type == CUSTOM_MMSC && mmc->started)
id = mm7http_send(mmc,e, from, lto, m, &err, &retry);
else if (mmc->type == CUSTOM_MMSC && mmc->started) {
Octstr *to = gwlist_get(lto, 0); /* XXX Send one at a time*/
id = mmc->fns->send_msg(mmc->data,
from, to, transid, linkedid, vasid,
service_code, m, hdrs, &err, &retry);
}
#if 0
else if (mmc->type == MM4_MMSC && mmc->started)
(void )0; /* Already sent above */
@ -1562,124 +1574,27 @@ static int mms_sendtommsc(MmscGrp *mmc, MmsEnvelope *e, Octstr *to,
return ret;
}
typedef struct MRcpt_t {
int smtp_flag;
MmscGrp *mmc;
List *rto; /* List of envelope */
} MRcpt_t;
static int sendMsg(MmsEnvelope *e)
static int cmp_mrcpt(struct MRcpt_t *m, MmscGrp *mmc)
{
MmsMsg *msg = NULL;
int i, n;
Octstr *otransid = e->hdrs ? http_header_value(e->hdrs, octstr_imm("X-Mbuni-TransactionID")) : NULL;
if ((msg = qfs->mms_queue_getdata(e)) == NULL) {
mms_error(0, "MM7", NULL, "MMSBox queue error: Failed to load message for queue id [%s]!", e->xqfname);
MMSC_ISSUE_ALARM(NULL, MMSBOX_ALARM_RETRIEVE_MMS_ERROR, 4);
goto done2;
} else
MMSC_CLEAR_ALARM(NULL, MMSBOX_ALARM_RETRIEVE_MMS_ERROR);
if (mmc == NULL && m->smtp_flag)
return 1;
else
return (mmc && mmc->id && m->mmc && m->mmc->id) && (octstr_case_compare(m->mmc->id, mmc->id) == 0);
}
for (i = 0, n = gwlist_len(e->to); i<n; i++) {
int res = MMS_SEND_OK;
MmsEnvelopeTo *to = gwlist_get(e->to, i);
Octstr *err = NULL, *x;
static void process_send_res(MmsEnvelope *e, MmsMsg *msg,
MmsEnvelopeTo *to, MmscGrp *mmc,
int res, Octstr *err, List *errl, Octstr *new_msgid,
int first_one)
{
time_t tnow = time(NULL);
MmscGrp *mmc = NULL;
Octstr *new_msgid = NULL;
List *errl = NULL;
int is_email = 0;
Octstr *requested_mmsc = NULL;
if (!to || !to->process)
continue;
if (e->expiryt != 0 && /* Handle message expiry. */
e->expiryt < tnow) {
err = octstr_format("MMSC error: Message expired while sending to %S!", to->rcpt);
res = MMS_SEND_ERROR_FATAL;
goto done;
} else if (e->attempts >= maxsendattempts) {
err = octstr_format("MMSBox error: Failed to deliver to "
"%S after %ld attempts. (max attempts allowed is %ld)!",
to->rcpt, e->attempts,
maxsendattempts);
res = MMS_SEND_ERROR_FATAL;
goto done;
}
is_email = (octstr_search_char(to->rcpt, '@', 0) > 0);
x = octstr_format("X-Mbuni-Via-%d", i);
requested_mmsc = e->hdrs ? http_header_value(e->hdrs, x) : NULL;
octstr_destroy(x);
if ((mmc = get_handler_mmc(requested_mmsc ? requested_mmsc : e->viaproxy, to->rcpt, e->from)) == NULL &&
!is_email) {
err = octstr_format("MMSBox error: Failed to deliver to "
"%S. Don't know how to route!",
to->rcpt);
res = MMS_SEND_ERROR_TRANSIENT;
goto done;
}
if (is_email || (mmc->type == MM4_MMSC && mmc->started)) { /* Handle MM4 recipient here as well */
int j = octstr_case_search(e->from, octstr_imm("/TYPE=PLMN"), 0);
int k = octstr_case_search(e->from, octstr_imm("/TYPE=IPv"), 0);
int len = octstr_len(e->from);
Octstr *pfrom, *xto;
if (j > 0 && j - 1 + sizeof "/TYPE=PLMN" == len)
pfrom = octstr_copy(e->from, 0, j);
else if (k > 0 && k + sizeof "/TYPE=IPv" == len)
pfrom = octstr_copy(e->from, 0, k);
else
pfrom = octstr_duplicate(e->from);
if (!is_email)
xto = octstr_format("%S@%S", to->rcpt,
mmc && octstr_str_compare(mmc->mmsc_url, "*") != 0 ? mmc->mmsc_url :
octstr_imm("unknown"));
else
xto = octstr_duplicate(to->rcpt);
if (octstr_search_char(e->from, '@', 0) < 0)
octstr_format_append(pfrom,"@%S", myhostname);
res = mms_sendtoemail(pfrom, xto,
e->subject ? e->subject : octstr_imm(""),
e->msgId, msg, 0, &err, octstr_get_cstr(sendmail_cmd),
myhostname, 0, 0,
"",
"", 0,
e->xqfname,
e->hdrs, smtp_relay.host, smtp_relay.port);
if (res == MMS_SEND_OK || res == MMS_SEND_QUEUED) {
new_msgid = e->msgId ? octstr_duplicate(e->msgId) : octstr_create("00001"); /* Fake it */
mmsbox_event_cb(NULL, MM7_TAG_SubmitReq, 1, octstr_imm("1.0"), 200,
mms_msgsize(msg), e->attempts, pfrom,
to->rcpt,NULL, NULL, e->hdrs, NULL);
}
octstr_destroy(pfrom);
octstr_destroy(xto);
} else {
res = mms_sendtommsc(mmc, e,
to->rcpt,
otransid,
msg,
&new_msgid,
&errl);
if (errl)
err = http_header_value(errl, octstr_imm("X-Mbuni-Error"));
if (new_msgid && e->hdrs) { /* Record it */
Octstr *x = octstr_format("X-Mbuni-Received-Message-Id-%d", i);
http_header_remove_all(e->hdrs, octstr_get_cstr(x));
http_header_add(e->hdrs, octstr_get_cstr(x), octstr_get_cstr(new_msgid));
octstr_destroy(x);
}
}
done:
if (res == MMS_SEND_OK || res == MMS_SEND_QUEUED) {
to->process = 0;
@ -1696,10 +1611,12 @@ static int sendMsg(MmsEnvelope *e)
}
if (mmc) {
if (first_one) {
if (res == MMS_SEND_OK || res == MMS_SEND_QUEUED)
mmc->mt_pdus++;
else
mmc->mt_errors++;
}
mmc->last_pdu = time(NULL);
return_mmsc_conn(mmc); /* important. */
}
@ -1747,23 +1664,224 @@ static int sendMsg(MmsEnvelope *e)
"%s MMSBox Outgoing Queue MMS Send: From %s, to %s, msgsize=%ld: %s",
SEND_ERROR_STR(res),
octstr_get_cstr(e->from), octstr_get_cstr(to->rcpt), e->msize, octstr_get_cstr(err));
}
/* Make a list of recpients up to max_rcpt */
static inline List *make_srcpt_list(List *rto, int max_rcpt)
{
List *l = gwlist_create();
MmsEnvelopeTo *xto;
while ((max_rcpt > 0) && (xto = gwlist_extract_first(rto)) != NULL) {
gwlist_append(l, xto);
max_rcpt--;
}
if (gwlist_len(l) == 0) {
gwlist_destroy(l, NULL);
l = NULL;
}
return l;
}
static int sendMsg(MmsEnvelope *e)
{
MmsMsg *msg = NULL;
int i, n;
Octstr *otransid = e->hdrs ? http_header_value(e->hdrs, octstr_imm("X-Mbuni-TransactionID")) : NULL;
MmscGrp _mmc_smtp = {.max_recipients = DEFAULT_SIMUL_RCPTS, .mutex = mutex_create()};
MRcpt_t smtp_h = {.mmc = &_mmc_smtp, .smtp_flag = 1, .rto = gwlist_create()}; /* Signals that recipient is on other end of smtp pipe */
List *mlist = NULL; /* List of MMScs */
MmsEnvelopeTo *to;
time_t tnow = time(NULL);
if ((msg = qfs->mms_queue_getdata(e)) == NULL) {
mms_error(0, "MM7", NULL, "MMSBox queue error: Failed to load message for queue id [%s]!", e->xqfname);
MMSC_ISSUE_ALARM(NULL, MMSBOX_ALARM_RETRIEVE_MMS_ERROR, 4);
goto done2;
} else
MMSC_CLEAR_ALARM(NULL, MMSBOX_ALARM_RETRIEVE_MMS_ERROR);
mlist = gwlist_create_ex(&smtp_h);
/* First split by mmc */
for (i = 0, n = gwlist_len(e->to); i<n; i++)
if ((to = gwlist_get(e->to, i)) != NULL && to->process && to->rcpt) {
Octstr *x, *err = NULL;
int is_email = (octstr_search_char(to->rcpt, '@', 0) > 0);
Octstr *requested_mmsc = NULL;
MmscGrp *mmc = NULL;
int res = MMS_SEND_OK;
MRcpt_t *m;
if (e->expiryt != 0 && /* Handle message expiry. */
e->expiryt < tnow) {
err = octstr_format("MMSC error: Message expired while sending to %S!", to->rcpt);
res = MMS_SEND_ERROR_FATAL;
goto done_route;
} else if (e->attempts >= maxsendattempts) {
err = octstr_format("MMSBox error: Failed to deliver to "
"%S after %ld attempts. (max attempts allowed is %ld)!",
to->rcpt, e->attempts,
maxsendattempts);
res = MMS_SEND_ERROR_FATAL;
goto done_route;
}
x = octstr_format("X-Mbuni-Via-%d", i);
requested_mmsc = e->hdrs ? http_header_value(e->hdrs, x) : NULL;
octstr_destroy(x);
if ((mmc = get_handler_mmc(requested_mmsc ? requested_mmsc : e->viaproxy, to->rcpt, e->from)) == NULL &&
!is_email) {
err = octstr_format("MMSBox error: Failed to deliver to "
"%S. Don't know how to route!",
to->rcpt);
res = MMS_SEND_ERROR_TRANSIENT;
goto done_route;
}
/* We know how to route: If mmc is null at this point, means mm4 recipient. */
if ((m = gwlist_search(mlist, mmc, (void *)cmp_mrcpt)) == NULL) { /* A new route, add recipient zone */
m = gw_malloc(sizeof *m);
m->smtp_flag = 0;
m->mmc = mmc;
m->rto = gwlist_create();
gwlist_append(mlist, m);
}
gwlist_append(m->rto, to); /* Record route. */
done_route:
if (res != MMS_SEND_OK)
process_send_res(e, msg, to, mmc, res, err, NULL, NULL, 0);
octstr_destroy(err);
octstr_destroy(requested_mmsc);
}
for (i = 0, n = gwlist_len(mlist); i<n && (e != NULL); i++) { /* Pass through MMSCs, delivering to one at a time. */
MRcpt_t *m = gwlist_get(mlist, i);
int maxrcpt = m->mmc->max_recipients;
List *lto;
/* Hive off maxrcpt each time and send. */
while (e != NULL && (lto = make_srcpt_list(m->rto, maxrcpt)) != NULL) {
MmscGrp *mmc = m->mmc;
Octstr *err = NULL;
Octstr *new_msgid = NULL;
List *errl = NULL;
int j, res = MMS_SEND_OK;
int is_email = m->smtp_flag;
int is_mm4 = (mmc && mmc->type == MM4_MMSC && mmc->started);
List *xto = gwlist_create();
Octstr *zto = NULL;
/* Make recipient list */
for (j = 0; j < gwlist_len(lto); j++) {
MmsEnvelopeTo *to = gwlist_get(lto, j);
Octstr *x = octstr_duplicate(to->rcpt);
int is_email = (octstr_search_char(to->rcpt, '@', 0) > 0);
if (is_mm4 && !is_email) /* Add host name of recipient domain */
octstr_format_append(x, "@%S",
mmc && octstr_str_compare(mmc->mmsc_url, "*") != 0 ? mmc->mmsc_url :
octstr_imm("unknown"));
gwlist_append(xto, x);
}
LINEARISE_STR_LIST(zto,xto,", ");
if (is_mm4 || is_email) { /* Handle mm4 as well */
int j = octstr_case_search(e->from, octstr_imm("/TYPE=PLMN"), 0);
int k = octstr_case_search(e->from, octstr_imm("/TYPE=IPv"), 0);
int len = octstr_len(e->from);
Octstr *pfrom;
if (j > 0 && j - 1 + sizeof "/TYPE=PLMN" == len)
pfrom = octstr_copy(e->from, 0, j);
else if (k > 0 && k + sizeof "/TYPE=IPv" == len)
pfrom = octstr_copy(e->from, 0, k);
else
pfrom = octstr_duplicate(e->from);
if (octstr_search_char(e->from, '@', 0) < 0)
octstr_format_append(pfrom,"@%S", myhostname);
res = mms_sendtoemail(pfrom, xto,
e->subject ? e->subject : octstr_imm(""),
e->msgId, msg, 0, &err, octstr_get_cstr(sendmail_cmd),
myhostname, 0, 0,
"",
"", 0,
e->xqfname,
e->hdrs, smtp_relay.host, smtp_relay.port);
if (res == MMS_SEND_OK || res == MMS_SEND_QUEUED) {
new_msgid = e->msgId ? octstr_duplicate(e->msgId) : octstr_create("00001"); /* Fake it */
mmsbox_event_cb(NULL, MM7_TAG_SubmitReq, 1, octstr_imm("1.0"), 200,
mms_msgsize(msg), e->attempts, pfrom,
zto,NULL, NULL, e->hdrs, NULL);
}
octstr_destroy(pfrom);
} else {
res = mms_sendtommsc(mmc, e,
xto,
otransid,
msg,
&new_msgid,
&errl);
if (errl)
err = http_header_value(errl, octstr_imm("X-Mbuni-Error"));
if (new_msgid && e->hdrs) { /* Record it */
Octstr *x = octstr_format("X-Mbuni-Received-Message-Id-%d", i);
http_header_remove_all(e->hdrs, octstr_get_cstr(x));
http_header_add(e->hdrs, octstr_get_cstr(x), octstr_get_cstr(new_msgid));
octstr_destroy(x);
}
}
/* For each recipient, process result */
for (j = 0; j < gwlist_len(lto); j++) {
MmsEnvelopeTo *to = gwlist_get(lto, j);
process_send_res(e, msg, to, mmc, res, err, errl, new_msgid, j == 0);
}
octstr_destroy(zto);
gwlist_destroy(xto, (void *)octstr_destroy);
octstr_destroy(new_msgid);
octstr_destroy(err);
http_destroy_headers(errl);
octstr_destroy(requested_mmsc);
e->lasttry = tnow;
if (qfs->mms_queue_update(e) == 1) {
e = NULL;
break; /* Queue entry gone. */
}
gwlist_destroy(lto, NULL);
}
}
done2:
mms_destroy(msg);
octstr_destroy(otransid);
/* Clear out mlist: */
for (i = 0; i < gwlist_len(mlist); i++) {
MRcpt_t *m = gwlist_get(mlist, i);
gwlist_destroy(m->rto, NULL); /* Clear list */
if (m != &smtp_h)
gw_free(m);
else
mutex_destroy(smtp_h.mmc->mutex);
}
gwlist_destroy(mlist, NULL);
if (e) { /* Update the queue if it is still valid (e.g. recipients not handled)
* XXX can this happen here??...
*/

View File

@ -663,6 +663,10 @@ static MmscGrp *start_mmsc_from_conf(mCfg *cfg, mCfgGrp *x, List *warnings, List
if (mms_cfg_get_bool(cfg, x, octstr_imm("strip-domain"), &m->strip_domain) < 0)
m->strip_domain = 1;
if (mms_cfg_get_int(cfg,x, octstr_imm("max-recipients"), &m->max_recipients) < 0 ||
m->max_recipients <= 0)
m->max_recipients = 1;
if (mms_cfg_get_int(cfg,x, octstr_imm("maximum-request-size"), &m->max_pkt_size) < 0 ||
m->max_pkt_size <= 0)
m->max_pkt_size = DEFAULT_MAX_PKT_SIZE;
@ -700,9 +704,13 @@ static MmscGrp *start_mmsc_from_conf(mCfg *cfg, mCfgGrp *x, List *warnings, List
m->settings = _mms_cfg_getx(cfg, x, octstr_imm("custom-settings"));
/* also load the libary. */
if ((m->fns = _mms_load_module(cfg, x, "mmsc-library", "mmsc_funcs", NULL)) == NULL) {
mms_error(0, "mmsbox", NULL, "failed to load MMSC libary functions from module!");
m->fns = &dummy_mmsc_funcs;
panic(errno, "failed to load MMSC libary functions from module, mmsc id <%s>!",
octstr_get_cstr(m->id));
}
m->max_recipients = 1;
mms_info(0, "mmsbox", NULL,"Loaded MMSC[%s], max recipients per transaction forced to 1",
octstr_get_cstr(m->id));
} else
WARNING("MMSBox: Unknown MMSC type [%s]!",
octstr_get_cstr(type));
@ -978,13 +986,11 @@ void mmsbox_settings_cleanup(void)
void return_mmsc_conn(MmscGrp *m)
{
if (m)
MMSBOX_MMSC_UNMARK_INUSE(m); /* Vital! */
/* now try and delete as many to-be-deleted mmc as possible */
delete_stale_mmsc(0);
}
/* handle message routing. */

View File

@ -82,6 +82,8 @@ typedef struct MmscGrp {
long max_pkt_size;
int strip_domain; /* MM4 only */
long max_recipients; /* Max recpients per transaction */
} MmscGrp;
#define DEFAULT_MAX_PKT_SIZE 1024*1024

View File

@ -181,14 +181,17 @@ static int sendMsg(MmsEnvelope *e)
e->msgId,
e->hdrs,
msg, &err);
else
res = mms_sendtoemail(pfrom, to->rcpt,
else {
List *lto = gwlist_create_ex(to->rcpt);
res = mms_sendtoemail(pfrom, lto,
e->subject ? e->subject : settings->mms_email_subject,
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), 0, e->xqfname,
e->hdrs, settings->smtp_relay, settings->smtp_port);
gwlist_destroy(lto, NULL);
}
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!
@ -575,6 +578,7 @@ static int mms_sendtoproxy(Octstr *from, Octstr *to,
{
Octstr *pto, *pfrom;
List *lto;
int x = MMS_SEND_ERROR_FATAL;
Octstr *xtransid; /* We make a fake transaction ID that includes 'to' field. */
@ -596,7 +600,8 @@ static int mms_sendtoproxy(Octstr *from, Octstr *to,
pfrom = from;
xtransid = octstr_format("%S-%s", to,transid);
x = mms_sendtoemail(from, pto,
lto = gwlist_create_ex(pto);
x = mms_sendtoemail(from, lto,
subject ? subject : settings->mms_email_subject,
msgid, msg, dlr,
error, proxy_sendmail_cmd ? octstr_get_cstr(proxy_sendmail_cmd) : sendmail_cmd,
@ -613,6 +618,7 @@ static int mms_sendtoproxy(Octstr *from, Octstr *to,
octstr_destroy(pto);
if (pfrom != from)
octstr_destroy(pfrom);
gwlist_destroy(lto, NULL);
return x;
}