From 573281fcad13fe840b7f0795ff36be5cfc5b420a Mon Sep 17 00:00:00 2001 From: Wilfried Goesgens Date: Fri, 27 Jul 2012 14:08:11 +0200 Subject: [PATCH] SMTP-Relaying: implement a method to choose a relay by sender email address or username --- citadel/modules/imap/imap_fetch.c | 2 +- citadel/modules/pop3/serv_pop3.c | 24 ++++- citadel/modules/smtp/serv_smtpqueue.c | 150 +++++++++++++++----------- citadel/modules/smtp/smtp_util.c | 3 +- citadel/msgbase.c | 38 +++++-- citadel/msgbase.h | 4 +- 6 files changed, 143 insertions(+), 78 deletions(-) diff --git a/citadel/modules/imap/imap_fetch.c b/citadel/modules/imap/imap_fetch.c index 82168170f..396e6070c 100644 --- a/citadel/modules/imap/imap_fetch.c +++ b/citadel/modules/imap/imap_fetch.c @@ -190,7 +190,7 @@ void imap_fetch_rfc822(long msgnum, const char *whichfmt) { CCC->redirect_buffer = NewStrBufPlain(NULL, SIZ); CtdlOutputMsg(msgnum, MT_RFC822, (need_body ? HEADERS_ALL : HEADERS_FAST), - 0, 1, NULL, SUPPRESS_ENV_TO + 0, 1, NULL, SUPPRESS_ENV_TO, NULL, NULL ); if (!need_body) IAPuts("\r\n"); /* extra trailing newline */ Imap->cached_rfc822 = CCC->redirect_buffer; diff --git a/citadel/modules/pop3/serv_pop3.c b/citadel/modules/pop3/serv_pop3.c index de4d7a065..97681da83 100644 --- a/citadel/modules/pop3/serv_pop3.c +++ b/citadel/modules/pop3/serv_pop3.c @@ -166,7 +166,14 @@ void pop3_add_message(long msgnum, void *userdata) { GetMetaData(&smi, msgnum); if (smi.meta_rfc822_length <= 0L) { CC->redirect_buffer = NewStrBufPlain(NULL, SIZ); - CtdlOutputMsg(msgnum, MT_RFC822, HEADERS_ALL, 0, 1, NULL, SUPPRESS_ENV_TO); + + CtdlOutputMsg(msgnum, + MT_RFC822, + HEADERS_ALL, + 0, 1, NULL, + SUPPRESS_ENV_TO, + NULL, NULL); + smi.meta_rfc822_length = StrLength(CC->redirect_buffer); FreeStrBuf(&CC->redirect_buffer); /* TODO: WHEW, all this for just knowing the length???? */ PutMetaData(&smi); @@ -324,9 +331,9 @@ void pop3_retr(char *argbuf) { cprintf("+OK Message %d:\r\n", which_one); CtdlOutputMsg(POP3->msgs[which_one - 1].msgnum, - MT_RFC822, HEADERS_ALL, 0, 1, NULL, - (ESC_DOT|SUPPRESS_ENV_TO) - ); + MT_RFC822, HEADERS_ALL, 0, 1, NULL, + (ESC_DOT|SUPPRESS_ENV_TO), + NULL, NULL); cprintf(".\r\n"); } @@ -356,7 +363,14 @@ void pop3_top(char *argbuf) { } CC->redirect_buffer = NewStrBufPlain(NULL, SIZ); - CtdlOutputMsg(POP3->msgs[which_one - 1].msgnum, MT_RFC822, HEADERS_ALL, 0, 1, NULL, SUPPRESS_ENV_TO); + + CtdlOutputMsg(POP3->msgs[which_one - 1].msgnum, + MT_RFC822, + HEADERS_ALL, + 0, 1, NULL, + SUPPRESS_ENV_TO, + NULL, NULL); + msgtext = CC->redirect_buffer; CC->redirect_buffer = NULL; diff --git a/citadel/modules/smtp/serv_smtpqueue.c b/citadel/modules/smtp/serv_smtpqueue.c index 0fa65bea2..3c4c2cb3e 100644 --- a/citadel/modules/smtp/serv_smtpqueue.c +++ b/citadel/modules/smtp/serv_smtpqueue.c @@ -473,7 +473,7 @@ void QItem_Handle_Attempted(OneQueItem *Item, StrBuf *Line, const char **Pos) /** * this one has to have the context for loading the message via the redirect buffer... */ -StrBuf *smtp_load_msg(OneQueItem *MyQItem, int n) +StrBuf *smtp_load_msg(OneQueItem *MyQItem, int n, char **Author, char **Address) { CitContext *CCC=CC; StrBuf *SendMsg; @@ -482,7 +482,9 @@ StrBuf *smtp_load_msg(OneQueItem *MyQItem, int n) CtdlOutputMsg(MyQItem->MessageID, MT_RFC822, HEADERS_ALL, 0, 1, NULL, - (ESC_DOT|SUPPRESS_ENV_TO) ); + (ESC_DOT|SUPPRESS_ENV_TO), + Author, + Address); SendMsg = CCC->redirect_buffer; CCC->redirect_buffer = NULL; @@ -704,6 +706,80 @@ void smtpq_do_bounce(OneQueItem *MyQItem, StrBuf *OMsgTxt) SMTPCM_syslog(LOG_DEBUG, "Done processing bounces\n"); } +ParsedURL *LoadRelayUrls(OneQueItem *MyQItem, + char *Author, + char *Address) +{ + int nRelays = 0; + ParsedURL *RelayUrls = NULL; + char mxbuf[SIZ]; + ParsedURL **Url = &MyQItem->URL; + + nRelays = get_hosts(mxbuf, "fallbackhost"); + if (nRelays > 0) { + StrBuf *All; + StrBuf *One; + const char *Pos = NULL; + All = NewStrBufPlain(mxbuf, -1); + One = NewStrBufPlain(NULL, StrLength(All) + 1); + + while ((Pos != StrBufNOTNULL) && + ((Pos == NULL) || + !IsEmptyStr(Pos))) + { + StrBufExtract_NextToken(One, All, &Pos, '|'); + if (!ParseURL(Url, One, DefaultMXPort)) { + SMTPC_syslog(LOG_DEBUG, + "Failed to parse: %s\n", + ChrPtr(One)); + } + else { + (*Url)->IsRelay = 1; + MyQItem->HaveRelay = 1; + } + } + FreeStrBuf(&All); + FreeStrBuf(&One); + } + nRelays = get_hosts(mxbuf, "smarthost"); + if (nRelays > 0) { + char *User; + StrBuf *All; + StrBuf *One; + const char *Pos = NULL; + All = NewStrBufPlain(mxbuf, -1); + One = NewStrBufPlain(NULL, StrLength(All) + 1); + + while ((Pos != StrBufNOTNULL) && + ((Pos == NULL) || + !IsEmptyStr(Pos))) + { + StrBufExtract_NextToken(One, All, &Pos, '|'); + User = strchr(ChrPtr(One), ' '); + if (User != NULL) { + if (!strcmp(User + 1, Author) || + !strcmp(User + 1, Address)) + StrBufCutAt(One, 0, User); + else + continue; + + } + if (!ParseURL(Url, One, DefaultMXPort)) { + SMTPC_syslog(LOG_DEBUG, + "Failed to parse: %s\n", + ChrPtr(One)); + } + else { + ///if (!Url->IsIP)) // todo dupe me fork ipv6 + (*Url)->IsRelay = 1; + MyQItem->HaveRelay = 1; + } + } + FreeStrBuf(&All); + FreeStrBuf(&One); + } + return RelayUrls; +} /* * smtp_do_procmsg() * @@ -713,6 +789,8 @@ void smtp_do_procmsg(long msgnum, void *userdata) { time_t now; int mynumsessions = num_sessions; struct CtdlMessage *msg = NULL; + char *Author = NULL; + char *Address = NULL; char *instr = NULL; StrBuf *PlainQItem; OneQueItem *MyQItem; @@ -721,8 +799,6 @@ void smtp_do_procmsg(long msgnum, void *userdata) { void *vQE; long len; const char *Key; - int nRelays = 0; - ParsedURL *RelayUrls = NULL; int HaveBuffers = 0; StrBuf *Msg =NULL; @@ -814,64 +890,6 @@ void smtp_do_procmsg(long msgnum, void *userdata) { return; } - { - char mxbuf[SIZ]; - ParsedURL **Url = &MyQItem->URL; - nRelays = get_hosts(mxbuf, "fallbackhost"); - if (nRelays > 0) { - StrBuf *All; - StrBuf *One; - const char *Pos = NULL; - All = NewStrBufPlain(mxbuf, -1); - One = NewStrBufPlain(NULL, StrLength(All) + 1); - - while ((Pos != StrBufNOTNULL) && - ((Pos == NULL) || - !IsEmptyStr(Pos))) - { - StrBufExtract_NextToken(One, All, &Pos, '|'); - if (!ParseURL(Url, One, DefaultMXPort)) { - SMTPC_syslog(LOG_DEBUG, - "Failed to parse: %s\n", - ChrPtr(One)); - } - else { - (*Url)->IsRelay = 1; - MyQItem->HaveRelay = 1; - } - } - FreeStrBuf(&All); - FreeStrBuf(&One); - } - nRelays = get_hosts(mxbuf, "smarthost"); - if (nRelays > 0) { - StrBuf *All; - StrBuf *One; - const char *Pos = NULL; - All = NewStrBufPlain(mxbuf, -1); - One = NewStrBufPlain(NULL, StrLength(All) + 1); - - while ((Pos != StrBufNOTNULL) && - ((Pos == NULL) || - !IsEmptyStr(Pos))) - { - StrBufExtract_NextToken(One, All, &Pos, '|'); - if (!ParseURL(Url, One, DefaultMXPort)) { - SMTPC_syslog(LOG_DEBUG, - "Failed to parse: %s\n", - ChrPtr(One)); - } - else { - ///if (!Url->IsIP)) // todo dupe me fork ipv6 - (*Url)->IsRelay = 1; - MyQItem->HaveRelay = 1; - } - } - FreeStrBuf(&All); - FreeStrBuf(&One); - } - - } It = GetNewHashPos(MyQItem->MailQEntries, 0); while (GetNextHashPos(MyQItem->MailQEntries, It, &len, &Key, &vQE)) @@ -910,11 +928,17 @@ void smtp_do_procmsg(long msgnum, void *userdata) { if (MyQItem->ActiveDeliveries > 0) { + ParsedURL *RelayUrls = NULL; int nActivated = 0; int n = MsgCount++; int m = MyQItem->ActiveDeliveries; int i = 1; - Msg = smtp_load_msg(MyQItem, n); + + Msg = smtp_load_msg(MyQItem, n, &Author, &Address); + RelayUrls = LoadRelayUrls(MyQItem, Author, Address); + if (Author != NULL) free (Author); + if (Address != NULL) free (Address); + It = GetNewHashPos(MyQItem->MailQEntries, 0); while ((i <= m) && (GetNextHashPos(MyQItem->MailQEntries, diff --git a/citadel/modules/smtp/smtp_util.c b/citadel/modules/smtp/smtp_util.c index 861ee9763..589f88553 100644 --- a/citadel/modules/smtp/smtp_util.c +++ b/citadel/modules/smtp/smtp_util.c @@ -271,7 +271,8 @@ void smtp_do_bounce(char *instr, StrBuf *OMsgTxt) CtdlOutputMsg(omsgid, MT_RFC822, HEADERS_ALL, - 0, 1, NULL, 0); + 0, 1, NULL, 0, + NULL, NULL); StrBufAppendBuf(BounceMB, CC->redirect_buffer, 0); FreeStrBuf(&CC->redirect_buffer); diff --git a/citadel/msgbase.c b/citadel/msgbase.c index 8cc816e81..abb47ca16 100644 --- a/citadel/msgbase.c +++ b/citadel/msgbase.c @@ -1654,7 +1654,9 @@ int CtdlOutputMsg(long msg_num, /* message number (local) to fetch */ int do_proto, /* do Citadel protocol responses? */ int crlf, /* Use CRLF newlines instead of LF? */ char *section, /* NULL or a message/rfc822 section */ - int flags /* various flags; see msgbase.h */ + int flags, /* various flags; see msgbase.h */ + char **Author, + char **Address ) { struct CitContext *CCC = CC; struct CtdlMessage *TheMessage = NULL; @@ -1732,6 +1734,17 @@ int CtdlOutputMsg(long msg_num, /* message number (local) to fetch */ *extract_encapsulated_message, NULL, NULL, (void *)&encap, 0 ); + + if ((Author != NULL) && (*Author == NULL)) + { + *Author = TheMessage->cm_fields['A']; + TheMessage->cm_fields['A'] = NULL; + } + if ((Address != NULL) && (*Address == NULL)) + { + *Address = TheMessage->cm_fields['F']; + TheMessage->cm_fields['F'] = NULL; + } CtdlFreeMessage(TheMessage); TheMessage = NULL; @@ -1762,6 +1775,17 @@ int CtdlOutputMsg(long msg_num, /* message number (local) to fetch */ /* Ok, output the message now */ if (retcode == CIT_OK) retcode = CtdlOutputPreLoadedMsg(TheMessage, mode, headers_only, do_proto, crlf, flags); + if ((Author != NULL) && (*Author == NULL)) + { + *Author = TheMessage->cm_fields['A']; + TheMessage->cm_fields['A'] = NULL; + } + if ((Address != NULL) && (*Address == NULL)) + { + *Address = TheMessage->cm_fields['F']; + TheMessage->cm_fields['F'] = NULL; + } + CtdlFreeMessage(TheMessage); return(retcode); @@ -2541,7 +2565,7 @@ void cmd_msg0(char *cmdbuf) msgid = extract_long(cmdbuf, 0); headers_only = extract_int(cmdbuf, 1); - CtdlOutputMsg(msgid, MT_CITADEL, headers_only, 1, 0, NULL, 0); + CtdlOutputMsg(msgid, MT_CITADEL, headers_only, 1, 0, NULL, 0, NULL, NULL); return; } @@ -2557,7 +2581,7 @@ void cmd_msg2(char *cmdbuf) msgid = extract_long(cmdbuf, 0); headers_only = extract_int(cmdbuf, 1); - CtdlOutputMsg(msgid, MT_RFC822, headers_only, 1, 1, NULL, 0); + CtdlOutputMsg(msgid, MT_RFC822, headers_only, 1, 1, NULL, 0, NULL, NULL); } @@ -2611,7 +2635,7 @@ void cmd_msg4(char *cmdbuf) msgid = extract_long(cmdbuf, 0); extract_token(section, cmdbuf, 1, '|', sizeof section); - CtdlOutputMsg(msgid, MT_MIME, 0, 1, 0, (section[0] ? section : NULL) , 0); + CtdlOutputMsg(msgid, MT_MIME, 0, 1, 0, (section[0] ? section : NULL) , 0, NULL, NULL); } @@ -2644,7 +2668,7 @@ void cmd_opna(char *cmdbuf) extract_token(desired_section, cmdbuf, 1, '|', sizeof desired_section); safestrncpy(CC->download_desired_section, desired_section, sizeof CC->download_desired_section); - CtdlOutputMsg(msgid, MT_DOWNLOAD, 0, 1, 1, NULL, 0); + CtdlOutputMsg(msgid, MT_DOWNLOAD, 0, 1, 1, NULL, 0, NULL, NULL); } @@ -2660,8 +2684,8 @@ void cmd_dlat(char *cmdbuf) extract_token(desired_section, cmdbuf, 1, '|', sizeof desired_section); safestrncpy(CC->download_desired_section, desired_section, sizeof CC->download_desired_section); - CtdlOutputMsg(msgid, MT_SPEW_SECTION, 0, 1, 1, NULL, 0); -} + CtdlOutputMsg(msgid, MT_SPEW_SECTION, 0, 1, 1, NULL, 0, NULL, NULL); +} /* diff --git a/citadel/msgbase.h b/citadel/msgbase.h index 017942f8d..f33cbb44a 100644 --- a/citadel/msgbase.h +++ b/citadel/msgbase.h @@ -165,7 +165,9 @@ int CtdlOutputMsg(long msg_num, /* message number (local) to fetch */ int do_proto, /* do Citadel protocol responses? */ int crlf, /* 0=LF, 1=CRLF */ char *section, /* output a message/rfc822 section */ - int flags /* should the bessage be exported clean? */ + int flags, /* should the bessage be exported clean? */ + char **Author, /* if you want to know the author of the message... */ + char **Address /* if you want to know the sender address of the message... */ ); /* Flags which may be passed to CtdlOutputMsg() and CtdlOutputPreLoadedMsg() */ -- 2.30.2