1
0
Fork 0
mbuni/mbuni/mmsc/mmsfromemail.c

406 lines
11 KiB
C

/*
* Mbuni - Open Source MMS Gateway
*
* Email2MMS and MM4 (incoming) interface
*
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
*
* Paul Bagyenda <bagyenda@dsmagic.com>
*
* This program is free software, distributed under the terms of
* the GNU General Public License, with a few exceptions granted (see LICENSE)
*/
#include <signal.h>
#include "mms_queue.h"
#include "mms_util.h"
static MmsBoxSettings *settings;
static Octstr *xfrom;
static Octstr *xto;
static Octstr *xproxy;
enum {TPLMN, TEMAIL, TOTHER} ttype;
static int find_own(int i, int argc, char *argv[]);
static int isphonenum(Octstr *s);
static void fixup_recipient(void);
static void fixup_sender(void);
static Cfg *cfg;
static List *proxyrelays;
int main(int argc, char *argv[])
{
int cfidx;
Octstr *fname;
CfgGroup *grp;
Octstr *log, *alog;
long loglevel;
MIMEEntity *mm;
MmsMsg *msg;
Octstr *email;
mms_lib_init();
srandom(time(NULL));
cfidx = get_and_set_debugs(argc, argv, find_own);
if (argv[cfidx] == NULL)
fname = octstr_imm("mmsc.conf");
else
fname = octstr_create(argv[cfidx]);
cfg = cfg_create(fname);
if (cfg_read(cfg) == -1)
panic(0, "Couldn't read configuration from '%s'.", octstr_get_cstr(fname));
octstr_destroy(fname);
info(0, "----------------------------------------");
info(0, " MMSC Email2MMS Tool version %s starting", MMSC_VERSION);
grp = cfg_get_single_group(cfg, octstr_imm("core"));
log = cfg_get(grp, octstr_imm("log-file"));
if (log != NULL) {
if (cfg_get_integer(&loglevel, grp, octstr_imm("log-level")) == -1)
loglevel = 0;
log_open(octstr_get_cstr(log), loglevel, GW_NON_EXCL);
octstr_destroy(log);
}
/* Get access log and open it. */
alog = cfg_get(grp, octstr_imm("access-log"));
if (alog) {
alog_open(octstr_get_cstr(alog), 1, 1);
octstr_destroy(alog);
}
/* Load proxy relays. */
proxyrelays = mms_proxy_relays(cfg);
/* Load settings. */
settings = mms_load_mmsbox_settings(cfg);
if (!settings)
panic(0, "No global MMSC configuration!");
if (!xto || !xfrom)
panic(0, "usage: %s -f from -t to!", argv[0]);
/* normalize recipient address, then if phone number,
* check whether we are allowed to process.
*/
fixup_recipient();
fixup_sender();
if (!xto ||
(ttype == TPLMN && !does_prefix_match(settings->email2mmsrelay_prefixes, xto))) {
error(0, " Not allowed to send to this recipient %s!",
xto ? octstr_get_cstr(xto) : "(null)");
return -1;
}
email = octstr_read_pipe(stdin);
if (!email || octstr_len(email) == 0) {
error(0, "Empty email message!");
return -1;
}
if ((mm = mime_octstr_to_entity(email)) == NULL) {
error(0, "Unable to decode mime entity!");
return -1;
}
octstr_destroy(email);
/* Take the entity, recode it --> remove base64 stuff, split headers. */
unbase64_mimeparts(mm);
unpack_mimeheaders(mm);
/* Now convert from mime to MMS message. */
msg = mms_frommime(mm);
mime_entity_destroy(mm);
if (!msg) {
error(0, "Unable to create MM!");
return -1;
}
switch(mms_messagetype(msg)) {
case MMS_MSGTYPE_SEND_REQ:
if (ttype != TPLMN ||/* We only send to phones from this interface */
!does_prefix_match(settings->email2mmsrelay_prefixes,
xto)) {
error(0, "Not allowed to send to %s!", octstr_get_cstr(xto));
} else {
List *lto = list_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;
int dlr;
octstr_format_append(xto, "/TYPE=PLMN");
list_append(lto, xto);
if (dreport &&
octstr_case_compare(dreport, octstr_imm("Yes")) == 0)
dlr = 1;
else
dlr = 0;
qf = mms_queue_add(xfrom, lto, msgid, NULL, xproxy, NULL,
0, time(NULL) + settings->default_msgexpiry, msg, NULL, dlr,
octstr_get_cstr(settings->global_queuedir));
if (qf) {
info(0, "Email2MMS Queued message to %s from %s (via %s) => %s",
octstr_get_cstr(xto), octstr_get_cstr(xfrom),
xproxy ? octstr_get_cstr(xproxy) : "(None)", octstr_get_cstr(qf));
octstr_destroy(qf);
/* 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 = list_create();
list_append(xlto, rto);
qf = mms_queue_add(settings->system_user, xlto, msgid, NULL,
xproxy, NULL,
0, time(NULL) + settings->default_msgexpiry,
mresp, NULL, 0,
octstr_get_cstr(settings->global_queuedir));
list_destroy(xlto, (list_item_destructor_t *)octstr_destroy);
mms_destroy(mresp);
octstr_destroy(qf);
}
mms_log("Received", xfrom, lto,
-1, msgid, NULL, xproxy, xproxy ? "MM4" : "MM3", NULL,NULL);
list_destroy(lto,NULL);
octstr_destroy(transid);
octstr_destroy(msgid);
if (dreport)
octstr_destroy(dreport);
}
break;
case MMS_MSGTYPE_SEND_CONF:
{
Octstr *transid = mms_get_header_value(msg, octstr_imm("X-Mms-Transaction-ID"));
Octstr *qf = mms_getqf_fromtransid(transid);
octstr_destroy(transid);
if (qf) {
MmsEnvelope *e = mms_queue_readenvelope(octstr_get_cstr(qf),
octstr_get_cstr(settings->mm4_queuedir),
1);
if (!e)
warning(0, "Received confirm MMS but cannot find message %s [%s] in queue!",
octstr_get_cstr(transid),
octstr_get_cstr(qf));
else {
MmsEnvelopeTo *t;
int i, n;
for (i = 0, n = list_len(e->to); i<n; i++)
if ((t = list_get(e->to, i)) != NULL)
t->process = 0; /* Should make it go away. */
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),
octstr_get_cstr(xfrom),
octstr_get_cstr(qf));
}
} else
warning(0, "Received confirm MMS but cannot find message %s in queue!",
octstr_get_cstr(transid));
}
break;
case MMS_MSGTYPE_DELIVERY_IND:
if (ttype != TPLMN ||/* We only send to phones from this interface */
!does_prefix_match(settings->email2mmsrelay_prefixes,
xto)) {
error(0, "Not allowed to send to %s!", octstr_get_cstr(xto));
} else {
List *lto = list_create();
Octstr *qf;
Octstr *msgid = mms_get_header_value(msg, octstr_imm("Message-ID"));
octstr_format_append(xto, "/TYPE=PLMN");
list_append(lto, xto);
qf = mms_queue_add(xfrom, lto, msgid, NULL,
xproxy, NULL,
0, time(NULL) + settings->default_msgexpiry, msg, NULL, 0,
octstr_get_cstr(settings->global_queuedir));
list_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);
}
octstr_destroy(msgid);
list_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 */
!does_prefix_match(settings->email2mmsrelay_prefixes,
xto)) {
error(0, "Not allowed to send to %s!", octstr_get_cstr(xto));
} else {
List *lto = list_create();
Octstr *qf;
Octstr *msgid = mms_get_header_value(msg, octstr_imm("Message-ID"));
octstr_format_append(xto, "/TYPE=PLMN");
list_append(lto, xto);
qf = mms_queue_add(xfrom, lto, msgid, NULL,
xproxy, NULL,
0, time(NULL) + settings->default_msgexpiry, msg, NULL,0,
octstr_get_cstr(settings->global_queuedir));
list_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);
}
octstr_destroy(msgid);
list_destroy(lto, NULL);
}
default:
{
int x = mms_messagetype(msg);
warning(0, "Unexpected message type: %d=>%s",
x,
mms_message_type_to_cstr(x));
break;
}
}
mms_destroy(msg);
return 0;
}
static int find_own(int i, int argc, char *argv[])
{
if (argv[i][1] == 'f')
if (i + 1 < argc) {
xfrom = octstr_create(argv[i+1]);
return 1;
} else
return -1;
else if (argv[i][1] == 't') /* recipient. */
if (i + 1 < argc) {
xto = octstr_create(argv[i+1]);
return 1;
} else
return -1;
else if (argv[i][1] == 'p') /* Proxy name if any. */
if (i + 1 < argc) {
xproxy = octstr_create(argv[i+1]);
return 1;
} else
return -1;
else
return -1;
}
static int isphonenum(Octstr *s)
{
int i = 0, n = octstr_len(s);
char *cs;
if (s && octstr_len(s) >= 1 &&
octstr_get_cstr(s)[0] == '+')
i++;
for ( cs = octstr_get_cstr(s); i<n; i++)
if (!gw_isdigit(cs[i]))
return 0;
return 1;
}
static void fixup_recipient(void)
{
int i;
Octstr *typ = NULL;
if (!xto) xto = octstr_imm("");
i = octstr_search_char(xto, '@', 0);
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));
octstr_delete(xto, i, octstr_len(xto));
}
if (isphonenum(xto) &&
(!typ || octstr_str_compare(typ, "TYPE=PLMN") == 0)) { /* A phone number. */
normalize_number(octstr_get_cstr(settings->unified_prefix), &xto);
ttype = TPLMN;
} else { /* For now everything else is email. */
ttype = TEMAIL;
}
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;
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"));
}