| /* |
| * VERSION 1.0 |
| * UDP MAIL system (Author: Alvin@Sushi) |
| * Requires INETD V0.60 or higher (INETD Author: Nostradamus@Zebedee) |
| */ |
| #pragma strict_types |
| #pragma no_clone |
| #pragma no_shadow |
| #pragma no_inherit |
| #pragma verbose_errors |
| #pragma combine_strings |
| //#pragma pedantic |
| //#pragma range_check |
| #pragma warn_deprecated |
| |
| #include <udp.h> |
| #include <udp_mail.h> |
| |
| #ifdef DEBUG |
| #undef DEBUG |
| #endif |
| #define DEBUG(x) |
| |
| mapping spool_item; |
| |
| static string *spool; |
| |
| private int match_mud_name(string mudname, string match_str) { |
| return mudname[0..sizeof(match_str)-1] == match_str; |
| } |
| |
| static void save_spool_item() |
| { |
| string name; |
| int count; |
| |
| if(!spool_item || !mappingp(spool_item) || spool_item==([])) |
| return; |
| |
| do { |
| ++count; |
| name=spool_item[UDPMS_DEST]+"-"+to_string(count); |
| } while(spool && member(spool, name)!=-1); |
| |
| save_object(UDPM_SPOOL_DIR+name); |
| |
| if(!spool || !sizeof(spool)) |
| spool = ({ name }); |
| else |
| spool += ({ name }); |
| } |
| |
| /* forward declaration */ |
| void deliver_mail(string recipient,string mud,string from, |
| string subj,string mail_body,int status_flag,string spool_name); |
| |
| /* forward declaration */ |
| static void start_retry_callout(); |
| |
| static void remove_from_spool(string spool_file) |
| { |
| int idx; |
| |
| if(spool && (idx=member(spool,spool_file))!=-1) |
| { |
| spool -= ({ spool_file }); |
| if(!sizeof(spool)) |
| spool=0; |
| } |
| |
| if(file_size("/"+UDPM_SPOOL_DIR+spool_file+".o")>0) |
| if(!rm("/"+UDPM_SPOOL_DIR+spool_file+".o")) |
| log_file(INETD_LOG_FILE,"UPD_MAIL: Can't delete spool file "+ |
| "/"+UDPM_SPOOL_DIR+spool_file+".o"); |
| } |
| |
| static void retry_send() |
| { |
| int i; |
| string msg; |
| |
| if(!spool || !sizeof(spool)) return; |
| |
| for(i=0;i<sizeof(spool);++i) |
| { |
| if(!restore_object(UDPM_SPOOL_DIR+spool[i])) |
| { |
| log_file(INETD_LOG_FILE,"UDP_MAIL: Falied to restore spool file "+ |
| UDPM_SPOOL_DIR+spool[i]); |
| continue; |
| } |
| |
| if(time() - spool_item[UDPMS_TIME] > UDPM_SEND_FAIL*60) |
| { |
| msg="Reason: Unable to connect to site \""+spool_item[UDPMS_DEST]+ |
| "\"\n\nINCLUDED MESSAGE FOLLOWS :-\n\n"+ |
| "To: "+spool_item[UDPMS_TO]+"\n"+ |
| "Subject: "+spool_item[UDPMS_SUBJECT]+"\n"+ |
| spool_item[UDPMS_BODY]; |
| |
| LOCAL_MAILER->deliver_mail( |
| spool_item[UDPMS_FROM], /* TO */ |
| "Mailer@"+LOCAL_NAME, /* FROM */ |
| "Bounced Mail", /* SUBJECT */ |
| msg /* MAIL BODY */ |
| ); |
| remove_from_spool(spool[i]); |
| return; |
| } |
| |
| deliver_mail( |
| spool_item[UDPMS_TO], |
| spool_item[UDPMS_DEST], |
| spool_item[UDPMS_FROM], |
| spool_item[UDPMS_SUBJECT], |
| spool_item[UDPMS_BODY], |
| UDPM_STATUS_IN_SPOOL, |
| spool[i]); |
| } |
| |
| start_retry_callout(); |
| } |
| |
| static void start_retry_callout() |
| { |
| if(find_call_out("retry_send")!= -1 ) return; |
| |
| call_out("retry_send",UDPM_RETRY_SEND*60); |
| } |
| |
| static void failed_to_deliver(mapping data) |
| { |
| string msg; |
| object obj; |
| |
| if(!data[SYSTEM] || data[SYSTEM] != TIME_OUT) |
| { |
| msg="Reason: Error in connection to remote site \""+data[NAME]+"\"\n\n"+ |
| "INCLUDED MESSAGE FOLLOWS :-\n\n"+ |
| "To: "+data[RECIPIENT]+"\n"+ |
| "Subject: "+data[UDPM_SUBJECT]+"\n"+data[DATA]; |
| |
| LOCAL_MAILER->deliver_mail( |
| data[UDPM_WRITER], /* TO */ |
| "Mailer@"+LOCAL_NAME, /* FROM */ |
| "Bounced Mail", /* SUBJECT */ |
| msg /* MAIL BODY */ |
| ); |
| return; |
| } |
| |
| /* OK transmission timed out.. place in mail spool */ |
| |
| if((obj=find_player(data[UDPM_WRITER]))) |
| { |
| tell_object(obj,"Mail delivery to "+data[RECIPIENT]+"@"+data[NAME]+ |
| " Timed Out. Placing mail in spool.\n"); |
| } |
| |
| spool_item=([ |
| UDPMS_TIME: time(), |
| UDPMS_TO: data[RECIPIENT], |
| UDPMS_DEST: data[NAME], |
| UDPMS_FROM: data[UDPM_WRITER], |
| UDPMS_SUBJECT: data[UDPM_SUBJECT], |
| UDPMS_BODY: data[DATA] |
| ]); |
| |
| save_spool_item(); |
| |
| start_retry_callout(); |
| } |
| |
| static void get_pending_deliveries() |
| { |
| string *entries; |
| int i; |
| |
| entries=get_dir(UDPM_SPOOL_DIR+"*.o"); |
| if(!entries || !sizeof(entries)) return; |
| |
| spool=allocate(sizeof(entries)); |
| for(i=0;i<sizeof(entries);++i) |
| spool[i]=entries[i][0..<3]; |
| |
| start_retry_callout(); |
| } |
| |
| void create() |
| { |
| seteuid(getuid(this_object())); |
| get_pending_deliveries(); |
| } |
| |
| /* |
| * Public routines |
| */ |
| |
| int query_valid_mail_host(string hostname) |
| { |
| string *match; |
| |
| match=filter(m_indices((mapping)INETD->query("hosts")), |
| #'match_mud_name,lower_case(hostname)); |
| |
| return (sizeof(match)==1); |
| } |
| |
| void deliver_mail(string recipient,string mud,string from, |
| string subj,string mail_body,int status_flag,string spool_name) |
| { |
| mapping data; |
| |
| // Geloggt wird, wenn ein aufrufendes Objekt nicht sicher ist. |
| if (object_name(previous_object())[0..7]!="/secure/") |
| write_file("/secure/ARCH/DELIVER_MAIL", |
| sprintf("%s : Aufruf von /secure/udp_mail->deliver_mail()\n" |
| " Sender: %O Empfaenger: %O@%O\n PO: %O TI: %O TP:%O\n\n", |
| ctime(time()),from, recipient, mud, |
| previous_object(), this_interactive(), this_player())); |
| |
| data=([ |
| REQUEST: "mail", |
| RECIPIENT: recipient, |
| SENDER: this_object(), |
| UDPM_STATUS: status_flag, |
| UDPM_WRITER: lower_case(from), |
| UDPM_SUBJECT: subj, |
| UDPM_SPOOL_NAME: spool_name, |
| DATA: mail_body |
| ]); |
| |
| INETD->_send_udp(mud,data,1); |
| } |
| |
| void udp_reply(mapping data) |
| { |
| object sender; |
| |
| DEBUG(sprintf("MAILER RECEIVED %O\n",data)); |
| if (!member(data,UDPM_STATUS)) |
| { |
| DEBUG("BOUNCING\n"); |
| LOCAL_MAILER->deliver_mail( |
| data[UDPM_WRITER], /* TO */ |
| "INETD@"+data[NAME], /* FROM */ |
| "Bounced Mail(No mail support yet?)", /* SUBJECT */ |
| data[DATA] /* MAIL BODY */ |
| ); |
| if(data[UDPM_SPOOL_NAME]) |
| remove_from_spool(data[UDPM_SPOOL_NAME]); |
| } else |
| switch(data[UDPM_STATUS]) |
| { |
| case UDPM_STATUS_TIME_OUT: |
| failed_to_deliver(data); |
| break; |
| |
| case UDPM_STATUS_DELIVERED_OK: |
| if((sender=find_player(data[UDPM_WRITER]))) |
| { |
| tell_object(sender,"Mailer@"+data[NAME]+": "+ |
| "Mail to "+capitalize(data[DATA])+" delivered ok.\n"); |
| } |
| if(data[UDPM_SPOOL_NAME]) |
| remove_from_spool(data[UDPM_SPOOL_NAME]); |
| |
| break; |
| |
| case UDPM_STATUS_UNKNOWN_PLAYER: |
| LOCAL_MAILER->deliver_mail( |
| data[UDPM_WRITER], /* TO */ |
| "Mailer@"+data[NAME], /* FROM */ |
| "Bounced Mail", /* SUBJECT */ |
| data[DATA] /* MAIL BODY */ |
| ); |
| if(data[UDPM_SPOOL_NAME]) |
| remove_from_spool(data[UDPM_SPOOL_NAME]); |
| break; |
| |
| case UDPM_STATUS_IN_SPOOL: |
| /* Do nothing */ |
| break; |
| } |
| } |