summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pttbbs/mbbsd/mail.c968
1 files changed, 491 insertions, 477 deletions
diff --git a/pttbbs/mbbsd/mail.c b/pttbbs/mbbsd/mail.c
index 5932aeb6..0aeb8d79 100644
--- a/pttbbs/mbbsd/mail.c
+++ b/pttbbs/mbbsd/mail.c
@@ -1,128 +1,121 @@
/* $Id$ */
#include "bbs.h"
-static int mailkeep = 0;
-static int mailmaxkeep = 0;
-static char currmaildir[PATHLEN];
-static char msg_cc[] = ANSI_COLOR(32) "[群組名單]" ANSI_RESET "\n";
-static char listfile[] = "list.0";
-// check only 20 mails (one page) is enough.
-// #define NEWMAIL_CHECK_RANGE (1)
+////////////////////////////////////////////////////////////////////////
+// Build configuration
+#ifndef NEWMAIL_CHECK_RANGE
+// Scanning whole .DIR will be too slow - so we only check few mails.
// checking only 1 mail works more like brc style.
+// 20 (one page) or 5 may be good choices.
+// #define NEWMAIL_CHECK_RANGE (1)
#define NEWMAIL_CHECK_RANGE (5)
+#endif
+////////////////////////////////////////////////////////////////////////
+// Local definition
enum SHOWMAIL_MODES {
SHOWMAIL_NORM = 0,
SHOWMAIL_RANGE,
};
-static int showmail_mode = SHOWMAIL_NORM;
-int old_cross_post(int, fileheader_t* , const char *);
-
-// #ifdef USE_MAIL_AUTO_FORWARD
-int
-setforward(void)
-{
- char buf[PATHLEN], ip[50] = "", yn[4];
- FILE *fp;
- int flIdiotSent2Self = 0;
- int oidlen = strlen(cuser.userid);
- if (!HasBasicUserPerm(PERM_LOGINOK))
- return DONOTHING;
+struct ReadNewMailArg {
+ int idc;
+ int *delmsgs;
+ int delcnt;
+ int mrd;
+};
- vs_hdr("設定自動轉寄");
+////////////////////////////////////////////////////////////////////////
+// Local variables (to speed up)
+static int mailkeep = 0;
+static int mailmaxkeep = 0;
+static char currmaildir[PATHLEN];
+static char msg_cc[] = ANSI_COLOR(32) "[群組名單]" ANSI_RESET "\n";
+static char listfile[] = "list.0";
+static int showmail_mode = SHOWMAIL_NORM;
+static const onekey_t mail_comms[];
- outs(ANSI_COLOR(1;31) "\n\n"
- "由於許\多使用者有意或無意的設定錯誤間接造成自動轉寄被惡意使用,\n"
- "本站基於安全性及防止廣告信的考量,\n"
- "即日起自動轉寄的寄件者一律改為轉寄者的 ID。\n\n"
- "不便之處請多見諒。\n"
- ANSI_RESET "\n");
+////////////////////////////////////////////////////////////////////////
+// Prototype of shared/local functions
+int old_cross_post(int, fileheader_t* , const char *);
- setuserfile(buf, ".forward");
- if ((fp = fopen(buf, "r"))) {
- fscanf(fp, "%" toSTR(sizeof(ip)) "s", ip);
- fclose(fp);
- }
- getdata_buf(b_lines - 1, 0, "請輸入自動轉寄的Email: ",
- ip, sizeof(ip), DOECHO);
+////////////////////////////////////////////////////////////////////////
+// Core utility functions
- if (strchr(ip, '@') == NULL)
- {
- // check if this is a valid local user
- if (searchuser(ip, ip) <= 0)
- {
- unlink(buf);
- vmsg("轉寄對象不存在,已取消自動轉寄。");
- return 0;
- }
- }
-
- /* anti idiots */
- if (strncasecmp(ip, cuser.userid, oidlen) == 0)
- {
- int addrlen = strlen(ip);
- if( addrlen == oidlen ||
- (addrlen > oidlen &&
- strcasecmp(ip + oidlen, str_mail_address) == 0))
- flIdiotSent2Self = 1;
- }
+int
+invalidaddr(const char *origaddr)
+{
+ const char *addr = origaddr;
+ if (!*addr)
+ return 1; /* blank */
- if (ip[0] && ip[0] != ' ' && !flIdiotSent2Self) {
- getdata(b_lines, 0, "確定開啟自動轉信功\能?(Y/n)", yn, sizeof(yn),
- LCECHO);
- if (yn[0] != 'n' && (fp = fopen(buf, "w"))) {
- fputs(ip, fp);
- fclose(fp);
- vmsg("設定完成!");
- return 0;
- }
+ while (*addr) {
+ if (not_alnum(*addr) && !strchr("[].@-_+", *addr)) {
+#ifdef DEBUG_FWDADDRERR
+ int c = (*addr) & 0xff;
+ clear();
+ mvouts(
+ 2, 0,
+ "您輸入的位址錯誤 (address error)。 \n\n"
+ "由於最近許\多人反應打入正確的位址(id或mail)後系統會判斷錯誤\n"
+ "但檢查不出原因,所以我們需要正確的錯誤回報。\n\n"
+ "如果你確實打錯了,請直接略過下面的說明。\n"
+ "如果你認為你輸入的位址確實是對的,請把下面的訊息複製起來\n"
+ "並貼到 " BN_BUGREPORT " 板。本站為造成不便深感抱歉。\n\n"
+ ANSI_COLOR(1;33));
+ prints("原始輸入位址: [%s]\n"
+ "錯誤位置: 第 %d 字元: 0x%02X [ %c ]" ANSI_RESET "\n",
+ origaddr, (int)(addr - origaddr + 1), c, c);
+ vmsg("請按任意鍵繼續");
+ clear();
+#endif
+ return 1;
+ }
+ addr++;
}
- unlink(buf);
- if(flIdiotSent2Self)
- vmsg("自動轉寄是不會設定給自己的,想取消用空白就可以了。");
- else
- vmsg("取消自動轉信!");
return 0;
}
-// #endif // USE_MAIL_AUTO_FORWARD
-int
-toggle_showmail_mode(void)
-{
- showmail_mode ++;
- showmail_mode %= SHOWMAIL_RANGE;
- return FULLUPDATE;
-}
int
-built_mail_index(void)
+load_mailalert(const char *userid)
{
- char genbuf[128];
+ struct stat st;
+ char maildir[PATHLEN];
+ int fd;
+ register int num;
+ fileheader_t my_mail;
- move(b_lines - 4, 0);
- outs("本功\能只在信箱檔毀損時使用," ANSI_COLOR(1;33) "無法" ANSI_RESET "救回被刪除的信件。\n"
- "除非您清楚這個功\能的作用,否則" ANSI_COLOR(1;33) "請不要使用" ANSI_RESET "。\n"
- "警告:任意的使用將導致" ANSI_COLOR(1;33) "不可預期的結果" ANSI_RESET "!\n");
- getdata(b_lines - 1, 0,
- "確定重建信箱?(y/N)", genbuf, 3,
- LCECHO);
- if (genbuf[0] != 'y')
- return FULLUPDATE;
+ sethomedir(maildir, userid);
+ if (!HasUserPerm(PERM_BASIC))
+ return 0;
+ if (stat(maildir, &st) < 0)
+ return 0;
+ num = st.st_size / sizeof(fileheader_t);
+ if (num <= 0)
+ return 0;
+ if (num > NEWMAIL_CHECK_RANGE)
+ num = NEWMAIL_CHECK_RANGE;
- snprintf(genbuf, sizeof(genbuf),
- BBSHOME "/bin/buildir " BBSHOME "/home/%c/%s > /dev/null",
- cuser.userid[0], cuser.userid);
- mvouts(b_lines - 1, 0, ANSI_COLOR(1;31) "已經處理完畢!! 諸多不便 敬請原諒~" ANSI_RESET);
- system(genbuf);
- pressanykey();
- return FULLUPDATE;
+ /* 看看有沒有信件還沒讀過?從檔尾回頭檢查,效率較高 */
+ if ((fd = open(maildir, O_RDONLY)) > 0) {
+ lseek(fd, st.st_size - sizeof(fileheader_t), SEEK_SET);
+ while (num--) {
+ read(fd, &my_mail, sizeof(fileheader_t));
+ if (!(my_mail.filemode & FILE_READ)) {
+ close(fd);
+ return ALERT_NEW_MAIL;
+ }
+ lseek(fd, -(off_t) 2 * sizeof(fileheader_t), SEEK_CUR);
+ }
+ close(fd);
+ }
+ return 0;
}
int
-sendalert(const char *userid, int alert)
-{
- int tuid;
+sendalert(const char *userid, int alert) {
+ int tuid;
if ((tuid = searchuser(userid, NULL)) == 0)
return -1;
@@ -131,9 +124,9 @@ sendalert(const char *userid, int alert)
}
int
-sendalert_uid(int uid, int alert){
- userinfo_t *uentp = NULL;
- int n, i;
+sendalert_uid(int uid, int alert) {
+ userinfo_t *uentp = NULL;
+ int n, i;
n = count_logins(uid, 0);
for (i = 1; i <= n; i++)
@@ -143,15 +136,17 @@ sendalert_uid(int uid, int alert){
return 0;
}
-int
-mail_muser(userec_t muser, const char *title, const char *filename)
+void setmailalert()
{
- return mail_id(muser.userid, title, filename, cuser.userid);
+ if(load_mailalert(cuser.userid))
+ currutmp->alerts |= ALERT_NEW_MAIL;
+ else
+ currutmp->alerts &= ~ALERT_NEW_MAIL;
}
int
-mail_log2id_text(const char *id, const char *title, const char *message, const char *owner, char newmail)
-{
+mail_log2id_text(const char *id, const char *title, const char *message,
+ const char *owner, char newmail) {
fileheader_t mhdr;
char dst[PATHLEN], dirf[PATHLEN];
@@ -172,8 +167,8 @@ mail_log2id_text(const char *id, const char *title, const char *message, const c
// TODO add header option?
int
-mail_log2id(const char *id, const char *title, const char *src, const char *owner, char newmail, char trymove)
-{
+mail_log2id(const char *id, const char *title, const char *src,
+ const char *owner, char newmail, char trymove) {
fileheader_t mhdr;
char dst[PATHLEN], dirf[PATHLEN];
@@ -224,50 +219,6 @@ mail_id(const char *id, const char *title, const char *src, const char *owner)
return 0;
}
-int
-invalidaddr(const char *addr)
-{
-#ifdef DEBUG_FWDADDRERR
- const char *origaddr = addr;
- char errmsg[PATHLEN];
-#endif
-
- if (*addr == '\0')
- return 1; /* blank */
-
- while (*addr) {
-#ifdef DEBUG_FWDADDRERR
- if (not_alnum(*addr) && !strchr("[].@-_+", *addr))
- {
- int c = (*addr) & 0xff;
- clear();
- move(2,0);
- outs(
- "您輸入的位址錯誤 (address error)。 \n\n"
- "由於最近許\多人反應打入正確的位址(id或email)後系統會判斷錯誤\n"
- "但檢查不出原因,所以我們需要正確的錯誤回報。\n\n"
- "如果你確實打錯了,請直接略過下面的說明。\n"
- "如果你認為你輸入的位址確實是對的,請把下面的訊息複製起來\n"
- "並貼到 " BN_BUGREPORT " 板。本站為造成不便深感抱歉。\n\n"
- ANSI_COLOR(1;33));
- sprintf(errmsg, "原始輸入位址: [%s]\n"
- "錯誤位置: 第 %d 字元: 0x%02X [ %c ]\n",
- origaddr, (int)(addr - origaddr+1), c, c);
- outs(errmsg);
- outs(ANSI_RESET);
- vmsg("請按任意鍵繼續");
- clear();
- return 1;
- }
-#else
- if (not_alnum(*addr) && !strchr("[].@-_", *addr))
- return 1;
-#endif
- addr++;
- }
- return 0;
-}
-
void
m_init(void)
{
@@ -336,35 +287,9 @@ chk_mailbox_limit(void)
return MAILBOX_LIM_HARD;
}
-int
-chkmailbox(void)
-{
- m_init();
-
- switch (chk_mailbox_limit()) {
- case MAILBOX_LIM_HARD:
- bell();
- case MAILBOX_LIM_KEEP:
- bell();
- vmsgf("您保存信件數目 %d 超出上限 %d, 請整理", mailkeep, mailmaxkeep);
- return mailkeep;
-
- default:
- return 0;
- }
-}
-
-int
-chkmailbox_hard_limit() {
- if (chk_mailbox_limit() == MAILBOX_LIM_HARD) {
- vmsgf("您保存信件數目 %d 遠超出上限 %d, 請整理", mailkeep, mailmaxkeep);
- return 1;
- }
- return 0;
-}
-
static void
-do_hold_mail(const char *fpath, const char *receiver, const char *holder, const char *save_title)
+do_hold_mail(const char *fpath, const char *receiver, const char *holder,
+ const char *save_title)
{
char buf[PATHLEN], title[128];
char holder_dir[PATHLEN];
@@ -389,21 +314,6 @@ do_hold_mail(const char *fpath, const char *receiver, const char *holder, const
append_record_forward(holder_dir, &mymail, sizeof(mymail), holder);
}
-void
-hold_mail(const char *fpath, const char *receiver, const char *title)
-{
- char buf[4];
-
- getdata(b_lines - 1, 0,
- (HasUserFlag(UF_DEFBACKUP)) ?
- "已順利寄出,是否自存底稿(Y/N)?[Y] " :
- "已順利寄出,是否自存底稿(Y/N)?[N] ",
- buf, sizeof(buf), LCECHO);
-
- if (TOBACKUP(buf[0]))
- do_hold_mail(fpath, receiver, cuser.userid, title);
-}
-
int
do_innersend(const char *userid, char *mfpath, const char *title, char *newtitle)
{
@@ -456,6 +366,188 @@ do_innersend(const char *userid, char *mfpath, const char *title, char *newtitle
return 0;
}
+/* 寄站內信 */
+static int
+send_inner_mail(const char *fpath, const char *title, const char *receiver) {
+ char fname[PATHLEN];
+ fileheader_t mymail;
+ char rightid[IDLEN+1];
+
+ if (!searchuser(receiver, rightid))
+ return -2;
+
+ /* to avoid DDOS of disk */
+ sethomedir(fname, rightid);
+ if (strcmp(rightid, cuser.userid) == 0) {
+ if (chk_mailbox_limit())
+ return -4;
+ }
+
+ sethomepath(fname, rightid);
+ stampfile(fname, &mymail);
+ if (!strcmp(rightid, cuser.userid)) {
+ /* Using BBSNAME may be too loooooong. */
+ strlcpy(mymail.owner, "[站內]", sizeof(mymail.owner));
+ mymail.filemode = FILE_READ;
+ } else
+ strlcpy(mymail.owner, cuser.userid, sizeof(mymail.owner));
+ strlcpy(mymail.title, title, sizeof(mymail.title));
+ unlink(fname);
+ Copy(fpath, fname);
+ sethomedir(fname, rightid);
+ append_record_forward(fname, &mymail, sizeof(mymail), rightid);
+ sendalert(receiver, ALERT_NEW_MAIL);
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+// User-interface procedures
+int
+setforward(void) {
+ char buf[PATHLEN], ip[50] = "", yn[4];
+ FILE *fp;
+ int flIdiotSent2Self = 0;
+ int oidlen = strlen(cuser.userid);
+
+ if (!HasBasicUserPerm(PERM_LOGINOK))
+ return DONOTHING;
+
+ vs_hdr("設定自動轉寄");
+
+ outs(ANSI_COLOR(1;31) "\n\n"
+ "由於許\多使用者有意或無意的設定錯誤間接造成自動轉寄被惡意使用,\n"
+ "本站基於安全性及防止廣告信的考量,\n"
+ "即日起自動轉寄的寄件者一律改為轉寄者的 ID。\n\n"
+ "不便之處請多見諒。\n"
+ ANSI_RESET "\n");
+
+ setuserfile(buf, ".forward");
+ if ((fp = fopen(buf, "r"))) {
+ fscanf(fp, "%" toSTR(sizeof(ip)) "s", ip);
+ fclose(fp);
+ }
+ getdata_buf(b_lines - 1, 0, "請輸入自動轉寄的Email: ",
+ ip, sizeof(ip), DOECHO);
+
+ if (strchr(ip, '@') == NULL)
+ {
+ // check if this is a valid local user
+ if (searchuser(ip, ip) <= 0)
+ {
+ unlink(buf);
+ vmsg("轉寄對象不存在,已取消自動轉寄。");
+ return 0;
+ }
+ }
+
+ /* anti idiots */
+ if (strncasecmp(ip, cuser.userid, oidlen) == 0)
+ {
+ int addrlen = strlen(ip);
+ if( addrlen == oidlen ||
+ (addrlen > oidlen &&
+ strcasecmp(ip + oidlen, str_mail_address) == 0))
+ flIdiotSent2Self = 1;
+ }
+
+ if (ip[0] && ip[0] != ' ' && !flIdiotSent2Self) {
+ getdata(b_lines, 0, "確定開啟自動轉信功\能?(Y/n)", yn, sizeof(yn),
+ LCECHO);
+ if (yn[0] != 'n' && (fp = fopen(buf, "w"))) {
+ fputs(ip, fp);
+ fclose(fp);
+ vmsg("設定完成!");
+ return 0;
+ }
+ }
+ unlink(buf);
+ if(flIdiotSent2Self)
+ vmsg("自動轉寄是不會設定給自己的,想取消用空白就可以了。");
+ else
+ vmsg("取消自動轉信!");
+ return 0;
+}
+
+int
+toggle_showmail_mode(void)
+{
+ showmail_mode ++;
+ showmail_mode %= SHOWMAIL_RANGE;
+ return FULLUPDATE;
+}
+
+int
+built_mail_index(void)
+{
+ char genbuf[128];
+
+ move(b_lines - 4, 0);
+ outs("本功\能只在信箱檔毀損時使用," ANSI_COLOR(1;33) "無法" ANSI_RESET "救回被刪除的信件。\n"
+ "除非您清楚這個功\能的作用,否則" ANSI_COLOR(1;33) "請不要使用" ANSI_RESET "。\n"
+ "警告:任意的使用將導致" ANSI_COLOR(1;33) "不可預期的結果" ANSI_RESET "!\n");
+ getdata(b_lines - 1, 0,
+ "確定重建信箱?(y/N)", genbuf, 3,
+ LCECHO);
+ if (genbuf[0] != 'y')
+ return FULLUPDATE;
+
+ snprintf(genbuf, sizeof(genbuf),
+ BBSHOME "/bin/buildir " BBSHOME "/home/%c/%s > /dev/null",
+ cuser.userid[0], cuser.userid);
+ mvouts(b_lines - 1, 0, ANSI_COLOR(1;31) "已經處理完畢!! 諸多不便 敬請原諒~" ANSI_RESET);
+ system(genbuf);
+ pressanykey();
+ return FULLUPDATE;
+}
+
+int
+mail_muser(userec_t muser, const char *title, const char *filename)
+{
+ return mail_id(muser.userid, title, filename, cuser.userid);
+}
+
+int
+chkmailbox(void)
+{
+ m_init();
+
+ switch (chk_mailbox_limit()) {
+ case MAILBOX_LIM_HARD:
+ bell();
+ case MAILBOX_LIM_KEEP:
+ bell();
+ vmsgf("您保存信件數目 %d 超出上限 %d, 請整理", mailkeep, mailmaxkeep);
+ return mailkeep;
+
+ default:
+ return 0;
+ }
+}
+
+int
+chkmailbox_hard_limit() {
+ if (chk_mailbox_limit() == MAILBOX_LIM_HARD) {
+ vmsgf("您保存信件數目 %d 遠超出上限 %d, 請整理", mailkeep, mailmaxkeep);
+ return 1;
+ }
+ return 0;
+}
+
+void
+hold_mail(const char *fpath, const char *receiver, const char *title)
+{
+ char buf[4];
+
+ getdata(b_lines - 1, 0,
+ (HasUserFlag(UF_DEFBACKUP)) ?
+ "已順利寄出,是否自存底稿(Y/N)?[Y] " :
+ "已順利寄出,是否自存底稿(Y/N)?[N] ",
+ buf, sizeof(buf), LCECHO);
+
+ if (TOBACKUP(buf[0]))
+ do_hold_mail(fpath, receiver, cuser.userid, title);
+}
+
int
do_send(const char *userid, const char *title, const char *log_source)
{
@@ -988,12 +1080,181 @@ m_forward(int ent GCC_UNUSED, fileheader_t * fhdr, const char *direct GCC_UNUSED
return FULLUPDATE;
}
-struct ReadNewMailArg {
- int idc;
- int *delmsgs;
- int delcnt;
- int mrd;
-};
+int
+doforward(const char *direct, const fileheader_t * fh, int mode)
+{
+ static char address[STRLEN] = "";
+ char fname[PATHLEN];
+ char genbuf[PATHLEN];
+ int return_no;
+ const char *hostaddr;
+
+ if (!address[0] && strcasecmp(cuser.email, "x") != 0)
+ strlcpy(address, cuser.email, sizeof(address));
+
+ if( mode == 'U' ){
+ if ('y' != tolower(vmsg("請按 y 執行 uuencode。"
+ "若您不清楚什麼是 uuencode 請改用 F 轉寄。")))
+ return 1;
+ }
+ trim(address);
+
+ // if user has address and not the default 'x' (no-email)...
+ if (address[0]) {
+ snprintf(genbuf, sizeof(genbuf),
+ "確定轉寄給 [%s] 嗎(Y/N/Q)?[Y] ", address);
+ getdata(b_lines, 0, genbuf, fname, 3, LCECHO);
+
+ if (fname[0] == 'q') {
+ outmsg("取消轉寄");
+ return 1;
+ }
+ if (fname[0] == 'n')
+ address[0] = '\0';
+ }
+ if (!address[0]) {
+ do {
+ getdata(b_lines - 1, 0, "請輸入轉寄地址:", fname, 60, DOECHO);
+ if (fname[0]) {
+ if (strchr(fname, '.'))
+ strlcpy(address, fname, sizeof(address));
+ else
+ snprintf(address, sizeof(address),
+ "%s.bbs@%s", fname, MYHOSTNAME);
+ } else {
+ vmsg("取消轉寄");
+ return 1;
+ }
+ } while (mode == 'Z' && strstr(address, MYHOSTNAME));
+ }
+ if (mode == 'Z') {
+ if (strstr(address, MYHOSTNAME) ||
+ strstr(address, ".bbs@")) {
+ vmsg("不可使用 BBS 信箱。");
+ return 1;
+ }
+ }
+ // XXX bug: if user has already provided mail address...
+ /* according to our experiment, many users leave blanks */
+ trim(address);
+ if (invalidaddr(address))
+ return -2;
+
+ // decide if address is internet mail
+ hostaddr = strchr(address, '@');
+ if (hostaddr && strcasecmp(hostaddr + 1, MYHOSTNAME) == 0)
+ hostaddr = NULL;
+
+ outmsg("轉寄中請稍候...");
+ refresh();
+
+ /* 追蹤使用者 */
+ if (HasUserPerm(PERM_LOGUSER))
+ log_user("mailforward to %s ",address);
+
+ // 處理站內黑名單
+ do {
+ char xid[IDLEN+1], *dot;
+ char fpath[PATHLEN];
+ int i = 0;
+
+ strlcpy(xid, address, sizeof(xid));
+ dot = strchr(xid, '.');
+ if (dot) *dot = 0;
+ dot = strcasestr(address, ".bbs@");
+
+ if (dot) {
+ if (strcasecmp(strchr(dot, '@')+1, MYHOSTNAME) != 0)
+ break;
+ } else {
+ // accept only local name
+ if (strchr(address, '@'))
+ break;
+ }
+
+ // now the xid holds local name
+ if (!is_validuserid(xid) ||
+ searchuser(xid, xid) <= 0)
+ {
+ vmsg("找不到此使用者 ID。");
+ return 1;
+ }
+
+ // some stupid users set self as rejects.
+ if (strcasecmp(xid, cuser.userid) == 0)
+ break;
+
+ sethomefile(fpath, xid, FN_REJECT);
+ i = file_exist_record(fpath, cuser.userid);
+ sethomefile(fpath, xid, FN_OVERRIDES);
+
+ if (i && !file_exist_record(fpath, cuser.userid)) {
+ // We used to simply ignore here, and then people (especially those
+ // in BuyTogether and similiars) say "my mail is lost".
+ // After notifying SYSOPs, we believe it will be better to let all
+ // users know what's going on.
+ vmsg("無法寄信給此使用者");
+ return 1;
+ }
+ } while (0);
+
+ // PATHLEN will be used as command line, so we need it longer.
+ assert(PATHLEN >= 256);
+ if (mode == 'Z') {
+ assert(is_validuserid(cuser.userid));
+ assert(!invalidaddr(address));
+#ifdef MUTT_PATH
+ snprintf(fname, sizeof(fname),
+ TAR_PATH " -X " BBSHOME "/etc/ziphome.exclude "
+ "-czf /tmp/home.%s.tgz home/%c/%s; "
+ MUTT_PATH " -s 'home.%s.tgz' "
+ "-a /tmp/home.%s.tgz -- '%s' </dev/null;"
+ "rm /tmp/home.%s.tgz",
+ cuser.userid, cuser.userid[0], cuser.userid,
+ cuser.userid, cuser.userid, address, cuser.userid);
+ system(fname);
+ return 0;
+#else
+ snprintf(fname, sizeof(fname),
+ TAR_PATH " -X " BBSHOME "/etc/ziphome.exclude "
+ "-czf - home/%c/%s | "
+ "/usr/bin/uuencode %s.tgz > %s",
+ cuser.userid[0], cuser.userid, cuser.userid, direct);
+ system(fname);
+ strlcpy(fname, direct, sizeof(fname));
+#endif
+ } else if (mode == 'U') {
+ char tmp_buf[PATHLEN];
+
+ snprintf(fname, sizeof(fname), "/tmp/bbs.uu%05d", (int)currpid);
+ snprintf(tmp_buf, sizeof(tmp_buf),
+ "/usr/bin/uuencode %s/%s uu.%05d > %s",
+ direct, fh->filename, (int)currpid, fname);
+ system(tmp_buf);
+ } else if (mode == 'F') {
+ char tmp_buf[PATHLEN];
+
+ snprintf(fname, sizeof(fname), "/tmp/bbs.f%05d", (int)currpid);
+ snprintf(tmp_buf, sizeof(tmp_buf), "%s/%s", direct, fh->filename);
+ if (!dashf(tmp_buf)) {
+ unlink(fname);
+ return -1;
+ }
+ Copy(tmp_buf, fname);
+ } else
+ return -1;
+
+#ifdef USE_LOG_INTERNETMAIL
+ if (hostaddr)
+ log_filef("log/internet_mail.log", LOG_CREAT,
+ "%s [%s] %s -> %s: %s - %s\n",
+ Cdatelite(&now), __FUNCTION__,
+ cuser.userid, address, direct, fh->title);
+#endif
+ return_no = bsmtp(fname, fh->title, address, NULL);
+ unlink(fname);
+ return (return_no);
+}
static int
read_new_mail(void * voidfptr, void *optarg)
@@ -1100,14 +1361,6 @@ read_new_mail(void * voidfptr, void *optarg)
return 0;
}
-void setmailalert()
-{
- if(load_mailalert(cuser.userid))
- currutmp->alerts |= ALERT_NEW_MAIL;
- else
- currutmp->alerts &= ~ALERT_NEW_MAIL;
-}
-
int
m_new(void)
{
@@ -1760,6 +2013,31 @@ del_range_mail(int ent, fileheader_t * fhdr, char *direct)
return ret;
}
+int
+m_read(void)
+{
+ int back_bid;
+
+ if (!HasUserPerm(PERM_READMAIL))
+ return DONOTHING;
+
+ if (get_num_records(currmaildir, sizeof(fileheader_t))) {
+ curredit = EDIT_MAIL;
+ back_bid = currbid;
+ currbid = 0;
+ i_read(RMAIL, currmaildir, mailtitle, maildoent, mail_comms, -1);
+ currbid = back_bid;
+ curredit = 0;
+ setmailalert();
+ return 0;
+ } else {
+ outs("您沒有來信");
+ return XEASY;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+// Optional Features
#ifdef OUTJOBSPOOL
static int
@@ -1861,6 +2139,9 @@ mail_recycle_bin(int ent GCC_UNUSED,
}
#endif // USE_TIME_CAPSULE
+////////////////////////////////////////////////////////////////////////
+// Command List
+
static const onekey_t mail_comms[] = {
{ 0, NULL }, // Ctrl('A')
{ 0, NULL }, // Ctrl('B')
@@ -1959,63 +2240,8 @@ static const onekey_t mail_comms[] = {
{ 1, mail_recycle_bin }, // '~' 126
};
-int
-m_read(void)
-{
- int back_bid;
-
- if (!HasUserPerm(PERM_READMAIL))
- return DONOTHING;
-
- if (get_num_records(currmaildir, sizeof(fileheader_t))) {
- curredit = EDIT_MAIL;
- back_bid = currbid;
- currbid = 0;
- i_read(RMAIL, currmaildir, mailtitle, maildoent, mail_comms, -1);
- currbid = back_bid;
- curredit = 0;
- setmailalert();
- return 0;
- } else {
- outs("您沒有來信");
- return XEASY;
- }
-}
-
-/* 寄站內信 */
-static int
-send_inner_mail(const char *fpath, const char *title, const char *receiver)
-{
- char fname[PATHLEN];
- fileheader_t mymail;
- char rightid[IDLEN+1];
-
- if (!searchuser(receiver, rightid))
- return -2;
-
- /* to avoid DDOS of disk */
- sethomedir(fname, rightid);
- if (strcmp(rightid, cuser.userid) == 0) {
- if (chk_mailbox_limit())
- return -4;
- }
-
- sethomepath(fname, rightid);
- stampfile(fname, &mymail);
- if (!strcmp(rightid, cuser.userid)) {
- /* Using BBSNAME may be too loooooong. */
- strlcpy(mymail.owner, "[站內]", sizeof(mymail.owner));
- mymail.filemode = FILE_READ;
- } else
- strlcpy(mymail.owner, cuser.userid, sizeof(mymail.owner));
- strlcpy(mymail.title, title, sizeof(mymail.title));
- unlink(fname);
- Copy(fpath, fname);
- sethomedir(fname, rightid);
- append_record_forward(fname, &mymail, sizeof(mymail), rightid);
- sendalert(receiver, ALERT_NEW_MAIL);
- return 0;
-}
+////////////////////////////////////////////////////////////////////////
+// Mailer backend
#include <netdb.h>
#include <pwd.h>
@@ -2138,215 +2364,3 @@ bsmtp(const char *fpath, const char *title, const char *rcpt, const char *from)
return chrono;
}
#endif /* USE_BSMTP */
-
-int
-doforward(const char *direct, const fileheader_t * fh, int mode)
-{
- static char address[STRLEN] = "";
- char fname[PATHLEN];
- char genbuf[PATHLEN];
- int return_no;
- const char *hostaddr;
-
- if (!address[0] && strcasecmp(cuser.email, "x") != 0)
- strlcpy(address, cuser.email, sizeof(address));
-
- if( mode == 'U' ){
- if ('y' != tolower(vmsg("請按 y 執行 uuencode。"
- "若您不清楚什麼是 uuencode 請改用 F 轉寄。")))
- return 1;
- }
- trim(address);
-
- // if user has address and not the default 'x' (no-email)...
- if (address[0]) {
- snprintf(genbuf, sizeof(genbuf),
- "確定轉寄給 [%s] 嗎(Y/N/Q)?[Y] ", address);
- getdata(b_lines, 0, genbuf, fname, 3, LCECHO);
-
- if (fname[0] == 'q') {
- outmsg("取消轉寄");
- return 1;
- }
- if (fname[0] == 'n')
- address[0] = '\0';
- }
- if (!address[0]) {
- do {
- getdata(b_lines - 1, 0, "請輸入轉寄地址:", fname, 60, DOECHO);
- if (fname[0]) {
- if (strchr(fname, '.'))
- strlcpy(address, fname, sizeof(address));
- else
- snprintf(address, sizeof(address),
- "%s.bbs@%s", fname, MYHOSTNAME);
- } else {
- vmsg("取消轉寄");
- return 1;
- }
- } while (mode == 'Z' && strstr(address, MYHOSTNAME));
- }
- if (mode == 'Z') {
- if (strstr(address, MYHOSTNAME) ||
- strstr(address, ".bbs@")) {
- vmsg("不可使用 BBS 信箱。");
- return 1;
- }
- }
- // XXX bug: if user has already provided mail address...
- /* according to our experiment, many users leave blanks */
- trim(address);
- if (invalidaddr(address))
- return -2;
-
- // decide if address is internet mail
- hostaddr = strchr(address, '@');
- if (hostaddr && strcasecmp(hostaddr + 1, MYHOSTNAME) == 0)
- hostaddr = NULL;
-
- outmsg("轉寄中請稍候...");
- refresh();
-
- /* 追蹤使用者 */
- if (HasUserPerm(PERM_LOGUSER))
- log_user("mailforward to %s ",address);
-
- // 處理站內黑名單
- do {
- char xid[IDLEN+1], *dot;
- char fpath[PATHLEN];
- int i = 0;
-
- strlcpy(xid, address, sizeof(xid));
- dot = strchr(xid, '.');
- if (dot) *dot = 0;
- dot = strcasestr(address, ".bbs@");
-
- if (dot) {
- if (strcasecmp(strchr(dot, '@')+1, MYHOSTNAME) != 0)
- break;
- } else {
- // accept only local name
- if (strchr(address, '@'))
- break;
- }
-
- // now the xid holds local name
- if (!is_validuserid(xid) ||
- searchuser(xid, xid) <= 0)
- {
- vmsg("找不到此使用者 ID。");
- return 1;
- }
-
- // some stupid users set self as rejects.
- if (strcasecmp(xid, cuser.userid) == 0)
- break;
-
- sethomefile(fpath, xid, FN_REJECT);
- i = file_exist_record(fpath, cuser.userid);
- sethomefile(fpath, xid, FN_OVERRIDES);
-
- if (i && !file_exist_record(fpath, cuser.userid)) {
- // We used to simply ignore here, and then people (especially those
- // in BuyTogether and similiars) say "my mail is lost".
- // After notifying SYSOPs, we believe it will be better to let all
- // users know what's going on.
- vmsg("無法寄信給此使用者");
- return 1;
- }
- } while (0);
-
- // PATHLEN will be used as command line, so we need it longer.
- assert(PATHLEN >= 256);
- if (mode == 'Z') {
- assert(is_validuserid(cuser.userid));
- assert(!invalidaddr(address));
-#ifdef MUTT_PATH
- snprintf(fname, sizeof(fname),
- TAR_PATH " -X " BBSHOME "/etc/ziphome.exclude "
- "-czf /tmp/home.%s.tgz home/%c/%s; "
- MUTT_PATH " -s 'home.%s.tgz' "
- "-a /tmp/home.%s.tgz -- '%s' </dev/null;"
- "rm /tmp/home.%s.tgz",
- cuser.userid, cuser.userid[0], cuser.userid,
- cuser.userid, cuser.userid, address, cuser.userid);
- system(fname);
- return 0;
-#else
- snprintf(fname, sizeof(fname),
- TAR_PATH " -X " BBSHOME "/etc/ziphome.exclude "
- "-czf - home/%c/%s | "
- "/usr/bin/uuencode %s.tgz > %s",
- cuser.userid[0], cuser.userid, cuser.userid, direct);
- system(fname);
- strlcpy(fname, direct, sizeof(fname));
-#endif
- } else if (mode == 'U') {
- char tmp_buf[PATHLEN];
-
- snprintf(fname, sizeof(fname), "/tmp/bbs.uu%05d", (int)currpid);
- snprintf(tmp_buf, sizeof(tmp_buf),
- "/usr/bin/uuencode %s/%s uu.%05d > %s",
- direct, fh->filename, (int)currpid, fname);
- system(tmp_buf);
- } else if (mode == 'F') {
- char tmp_buf[PATHLEN];
-
- snprintf(fname, sizeof(fname), "/tmp/bbs.f%05d", (int)currpid);
- snprintf(tmp_buf, sizeof(tmp_buf), "%s/%s", direct, fh->filename);
- if (!dashf(tmp_buf)) {
- unlink(fname);
- return -1;
- }
- Copy(tmp_buf, fname);
- } else
- return -1;
-
-#ifdef USE_LOG_INTERNETMAIL
- if (hostaddr)
- log_filef("log/internet_mail.log", LOG_CREAT,
- "%s [%s] %s -> %s: %s - %s\n",
- Cdatelite(&now), __FUNCTION__,
- cuser.userid, address, direct, fh->title);
-#endif
- return_no = bsmtp(fname, fh->title, address, NULL);
- unlink(fname);
- return (return_no);
-}
-
-int
-load_mailalert(const char *userid)
-{
- struct stat st;
- char maildir[PATHLEN];
- int fd;
- register int num;
- fileheader_t my_mail;
-
- sethomedir(maildir, userid);
- if (!HasUserPerm(PERM_BASIC))
- return 0;
- if (stat(maildir, &st) < 0)
- return 0;
- num = st.st_size / sizeof(fileheader_t);
- if (num <= 0)
- return 0;
- if (num > NEWMAIL_CHECK_RANGE)
- num = NEWMAIL_CHECK_RANGE;
-
- /* 看看有沒有信件還沒讀過?從檔尾回頭檢查,效率較高 */
- if ((fd = open(maildir, O_RDONLY)) > 0) {
- lseek(fd, st.st_size - sizeof(fileheader_t), SEEK_SET);
- while (num--) {
- read(fd, &my_mail, sizeof(fileheader_t));
- if (!(my_mail.filemode & FILE_READ)) {
- close(fd);
- return ALERT_NEW_MAIL;
- }
- lseek(fd, -(off_t) 2 * sizeof(fileheader_t), SEEK_CUR);
- }
- close(fd);
- }
- return 0;
-}