MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame^] | 1 | /* |
| 2 | * VERSION 1.0 |
| 3 | * UDP MAIL system (Author: Alvin@Sushi) |
| 4 | * Requires INETD V0.60 or higher (INETD Author: Nostradamus@Zebedee) |
| 5 | */ |
| 6 | #pragma strict_types |
| 7 | #pragma no_clone |
| 8 | #pragma no_shadow |
| 9 | #pragma no_inherit |
| 10 | #pragma verbose_errors |
| 11 | #pragma combine_strings |
| 12 | //#pragma pedantic |
| 13 | //#pragma range_check |
| 14 | #pragma warn_deprecated |
| 15 | |
| 16 | #include <udp.h> |
| 17 | #include <udp_mail.h> |
| 18 | |
| 19 | #ifdef DEBUG |
| 20 | #undef DEBUG |
| 21 | #endif |
| 22 | #define DEBUG(x) |
| 23 | |
| 24 | mapping spool_item; |
| 25 | |
| 26 | static string *spool; |
| 27 | |
| 28 | private int match_mud_name(string mudname, string match_str) { |
| 29 | return mudname[0..sizeof(match_str)-1] == match_str; |
| 30 | } |
| 31 | |
| 32 | static void save_spool_item() |
| 33 | { |
| 34 | string name; |
| 35 | int count; |
| 36 | |
| 37 | if(!spool_item || !mappingp(spool_item) || spool_item==([])) |
| 38 | return; |
| 39 | |
| 40 | do { |
| 41 | ++count; |
| 42 | name=spool_item[UDPMS_DEST]+"-"+to_string(count); |
| 43 | } while(spool && member(spool, name)!=-1); |
| 44 | |
| 45 | save_object(UDPM_SPOOL_DIR+name); |
| 46 | |
| 47 | if(!spool || !sizeof(spool)) |
| 48 | spool = ({ name }); |
| 49 | else |
| 50 | spool += ({ name }); |
| 51 | } |
| 52 | |
| 53 | /* forward declaration */ |
| 54 | void deliver_mail(string recipient,string mud,string from, |
| 55 | string subj,string mail_body,int status_flag,string spool_name); |
| 56 | |
| 57 | /* forward declaration */ |
| 58 | static void start_retry_callout(); |
| 59 | |
| 60 | static void remove_from_spool(string spool_file) |
| 61 | { |
| 62 | int idx; |
| 63 | |
| 64 | if(spool && (idx=member(spool,spool_file))!=-1) |
| 65 | { |
| 66 | spool -= ({ spool_file }); |
| 67 | if(!sizeof(spool)) |
| 68 | spool=0; |
| 69 | } |
| 70 | |
| 71 | if(file_size("/"+UDPM_SPOOL_DIR+spool_file+".o")>0) |
| 72 | if(!rm("/"+UDPM_SPOOL_DIR+spool_file+".o")) |
| 73 | log_file(INETD_LOG_FILE,"UPD_MAIL: Can't delete spool file "+ |
| 74 | "/"+UDPM_SPOOL_DIR+spool_file+".o"); |
| 75 | } |
| 76 | |
| 77 | static void retry_send() |
| 78 | { |
| 79 | int i; |
| 80 | string msg; |
| 81 | |
| 82 | if(!spool || !sizeof(spool)) return; |
| 83 | |
| 84 | for(i=0;i<sizeof(spool);++i) |
| 85 | { |
| 86 | if(!restore_object(UDPM_SPOOL_DIR+spool[i])) |
| 87 | { |
| 88 | log_file(INETD_LOG_FILE,"UDP_MAIL: Falied to restore spool file "+ |
| 89 | UDPM_SPOOL_DIR+spool[i]); |
| 90 | continue; |
| 91 | } |
| 92 | |
| 93 | if(time() - spool_item[UDPMS_TIME] > UDPM_SEND_FAIL*60) |
| 94 | { |
| 95 | msg="Reason: Unable to connect to site \""+spool_item[UDPMS_DEST]+ |
| 96 | "\"\n\nINCLUDED MESSAGE FOLLOWS :-\n\n"+ |
| 97 | "To: "+spool_item[UDPMS_TO]+"\n"+ |
| 98 | "Subject: "+spool_item[UDPMS_SUBJECT]+"\n"+ |
| 99 | spool_item[UDPMS_BODY]; |
| 100 | |
| 101 | LOCAL_MAILER->deliver_mail( |
| 102 | spool_item[UDPMS_FROM], /* TO */ |
| 103 | "Mailer@"+LOCAL_NAME, /* FROM */ |
| 104 | "Bounced Mail", /* SUBJECT */ |
| 105 | msg /* MAIL BODY */ |
| 106 | ); |
| 107 | remove_from_spool(spool[i]); |
| 108 | return; |
| 109 | } |
| 110 | |
| 111 | deliver_mail( |
| 112 | spool_item[UDPMS_TO], |
| 113 | spool_item[UDPMS_DEST], |
| 114 | spool_item[UDPMS_FROM], |
| 115 | spool_item[UDPMS_SUBJECT], |
| 116 | spool_item[UDPMS_BODY], |
| 117 | UDPM_STATUS_IN_SPOOL, |
| 118 | spool[i]); |
| 119 | } |
| 120 | |
| 121 | start_retry_callout(); |
| 122 | } |
| 123 | |
| 124 | static void start_retry_callout() |
| 125 | { |
| 126 | if(find_call_out("retry_send")!= -1 ) return; |
| 127 | |
| 128 | call_out("retry_send",UDPM_RETRY_SEND*60); |
| 129 | } |
| 130 | |
| 131 | static void failed_to_deliver(mapping data) |
| 132 | { |
| 133 | string msg; |
| 134 | object obj; |
| 135 | |
| 136 | if(!data[SYSTEM] || data[SYSTEM] != TIME_OUT) |
| 137 | { |
| 138 | msg="Reason: Error in connection to remote site \""+data[NAME]+"\"\n\n"+ |
| 139 | "INCLUDED MESSAGE FOLLOWS :-\n\n"+ |
| 140 | "To: "+data[RECIPIENT]+"\n"+ |
| 141 | "Subject: "+data[UDPM_SUBJECT]+"\n"+data[DATA]; |
| 142 | |
| 143 | LOCAL_MAILER->deliver_mail( |
| 144 | data[UDPM_WRITER], /* TO */ |
| 145 | "Mailer@"+LOCAL_NAME, /* FROM */ |
| 146 | "Bounced Mail", /* SUBJECT */ |
| 147 | msg /* MAIL BODY */ |
| 148 | ); |
| 149 | return; |
| 150 | } |
| 151 | |
| 152 | /* OK transmission timed out.. place in mail spool */ |
| 153 | |
| 154 | if((obj=find_player(data[UDPM_WRITER]))) |
| 155 | { |
| 156 | tell_object(obj,"Mail delivery to "+data[RECIPIENT]+"@"+data[NAME]+ |
| 157 | " Timed Out. Placing mail in spool.\n"); |
| 158 | } |
| 159 | |
| 160 | spool_item=([ |
| 161 | UDPMS_TIME: time(), |
| 162 | UDPMS_TO: data[RECIPIENT], |
| 163 | UDPMS_DEST: data[NAME], |
| 164 | UDPMS_FROM: data[UDPM_WRITER], |
| 165 | UDPMS_SUBJECT: data[UDPM_SUBJECT], |
| 166 | UDPMS_BODY: data[DATA] |
| 167 | ]); |
| 168 | |
| 169 | save_spool_item(); |
| 170 | |
| 171 | start_retry_callout(); |
| 172 | } |
| 173 | |
| 174 | static void get_pending_deliveries() |
| 175 | { |
| 176 | string *entries; |
| 177 | int i; |
| 178 | |
| 179 | entries=get_dir(UDPM_SPOOL_DIR+"*.o"); |
| 180 | if(!entries || !sizeof(entries)) return; |
| 181 | |
| 182 | spool=allocate(sizeof(entries)); |
| 183 | for(i=0;i<sizeof(entries);++i) |
| 184 | spool[i]=entries[i][0..<3]; |
| 185 | |
| 186 | start_retry_callout(); |
| 187 | } |
| 188 | |
| 189 | void create() |
| 190 | { |
| 191 | seteuid(getuid(this_object())); |
| 192 | get_pending_deliveries(); |
| 193 | } |
| 194 | |
| 195 | /* |
| 196 | * Public routines |
| 197 | */ |
| 198 | |
| 199 | int query_valid_mail_host(string hostname) |
| 200 | { |
| 201 | string *match; |
| 202 | |
| 203 | match=filter(m_indices((mapping)INETD->query("hosts")), |
| 204 | #'match_mud_name,lower_case(hostname)); |
| 205 | |
| 206 | return (sizeof(match)==1); |
| 207 | } |
| 208 | |
| 209 | void deliver_mail(string recipient,string mud,string from, |
| 210 | string subj,string mail_body,int status_flag,string spool_name) |
| 211 | { |
| 212 | mapping data; |
| 213 | |
| 214 | // Geloggt wird, wenn ein aufrufendes Objekt nicht sicher ist. |
| 215 | if (object_name(previous_object())[0..7]!="/secure/") |
| 216 | write_file("/secure/ARCH/DELIVER_MAIL", |
| 217 | sprintf("%s : Aufruf von /secure/udp_mail->deliver_mail()\n" |
| 218 | " Sender: %O Empfaenger: %O@%O\n PO: %O TI: %O TP:%O\n\n", |
| 219 | ctime(time()),from, recipient, mud, |
| 220 | previous_object(), this_interactive(), this_player())); |
| 221 | |
| 222 | data=([ |
| 223 | REQUEST: "mail", |
| 224 | RECIPIENT: recipient, |
| 225 | SENDER: this_object(), |
| 226 | UDPM_STATUS: status_flag, |
| 227 | UDPM_WRITER: lower_case(from), |
| 228 | UDPM_SUBJECT: subj, |
| 229 | UDPM_SPOOL_NAME: spool_name, |
| 230 | DATA: mail_body |
| 231 | ]); |
| 232 | |
| 233 | INETD->_send_udp(mud,data,1); |
| 234 | } |
| 235 | |
| 236 | void udp_reply(mapping data) |
| 237 | { |
| 238 | object sender; |
| 239 | |
| 240 | DEBUG(sprintf("MAILER RECEIVED %O\n",data)); |
| 241 | if (!member(data,UDPM_STATUS)) |
| 242 | { |
| 243 | DEBUG("BOUNCING\n"); |
| 244 | LOCAL_MAILER->deliver_mail( |
| 245 | data[UDPM_WRITER], /* TO */ |
| 246 | "INETD@"+data[NAME], /* FROM */ |
| 247 | "Bounced Mail(No mail support yet?)", /* SUBJECT */ |
| 248 | data[DATA] /* MAIL BODY */ |
| 249 | ); |
| 250 | if(data[UDPM_SPOOL_NAME]) |
| 251 | remove_from_spool(data[UDPM_SPOOL_NAME]); |
| 252 | } else |
| 253 | switch(data[UDPM_STATUS]) |
| 254 | { |
| 255 | case UDPM_STATUS_TIME_OUT: |
| 256 | failed_to_deliver(data); |
| 257 | break; |
| 258 | |
| 259 | case UDPM_STATUS_DELIVERED_OK: |
| 260 | if((sender=find_player(data[UDPM_WRITER]))) |
| 261 | { |
| 262 | tell_object(sender,"Mailer@"+data[NAME]+": "+ |
| 263 | "Mail to "+capitalize(data[DATA])+" delivered ok.\n"); |
| 264 | } |
| 265 | if(data[UDPM_SPOOL_NAME]) |
| 266 | remove_from_spool(data[UDPM_SPOOL_NAME]); |
| 267 | |
| 268 | break; |
| 269 | |
| 270 | case UDPM_STATUS_UNKNOWN_PLAYER: |
| 271 | LOCAL_MAILER->deliver_mail( |
| 272 | data[UDPM_WRITER], /* TO */ |
| 273 | "Mailer@"+data[NAME], /* FROM */ |
| 274 | "Bounced Mail", /* SUBJECT */ |
| 275 | data[DATA] /* MAIL BODY */ |
| 276 | ); |
| 277 | if(data[UDPM_SPOOL_NAME]) |
| 278 | remove_from_spool(data[UDPM_SPOOL_NAME]); |
| 279 | break; |
| 280 | |
| 281 | case UDPM_STATUS_IN_SPOOL: |
| 282 | /* Do nothing */ |
| 283 | break; |
| 284 | } |
| 285 | } |