MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame^] | 1 | // MorgenGrauen MUDlib |
| 2 | // |
| 3 | // mailer.c |
| 4 | // |
| 5 | // $Id: mailer.c 9547 2016-04-17 19:27:47Z Zesstra $ |
| 6 | |
| 7 | /* |
| 8 | *------------------------------------------------------------ |
| 9 | * The mail demon. Receives mail from users and delivers it into |
| 10 | * the mail directory. |
| 11 | * |
| 12 | * Deepthought, Nightfall, 25-May-92 |
| 13 | * Remove-Functions : Jof, 29-June-92 |
| 14 | * Caching, DeleteUnreadFolder, small changes: Loco, 08-Feb-97 |
| 15 | * General clean-up and speed-up: Tiamak, 18-Jan-2000 |
| 16 | * DON'T USE restore_object any more, use GetFolders instead! |
| 17 | *------------------------------------------------------------ |
| 18 | * |
| 19 | * Save file format (sort of formal notation): |
| 20 | * |
| 21 | * mixed *folders = ({ |
| 22 | * ({ string name1; string name2; ... string nameN; }) |
| 23 | * ({ mixed *msgs1; mixed *msgs2; ... mixed *msgsN; }) |
| 24 | * }) |
| 25 | * |
| 26 | * Each msgs field is an array of messages: |
| 27 | * |
| 28 | * mixed *msgs = ({ mixed *message1; ... mixed *messageM }) |
| 29 | * |
| 30 | * A message is represented as an array with the following fields: |
| 31 | * |
| 32 | * mixed *message = ({ |
| 33 | * string from; |
| 34 | * string sender; |
| 35 | * string recipient; |
| 36 | * string *cc; |
| 37 | * string *bcc; |
| 38 | * string subject; |
| 39 | * string date; |
| 40 | * string id; |
| 41 | * string body; |
| 42 | * }) |
| 43 | * |
| 44 | * The mailer demon (/secure/mailer) provides the following functions: |
| 45 | * |
| 46 | * string *DeliverMail(mixed *message) |
| 47 | * Hand a mail message over to the mailer demon. The mailer |
| 48 | * demon extracts recipients from the recipient, cc and bcc |
| 49 | * fields and removes the bcc information. It then deposits |
| 50 | * the message to the mail files of all recipients. A valid |
| 51 | * message is shown above. Returns a list of successfully |
| 52 | * delivered recipients. |
| 53 | * |
| 54 | * int FingerMail(string user) |
| 55 | * Gives the number of unread messages a user has. |
| 56 | *------------------------------------------------------------ |
| 57 | */ |
| 58 | #pragma strict_types |
| 59 | #pragma no_clone |
| 60 | #pragma no_shadow |
| 61 | #pragma no_inherit |
| 62 | #pragma verbose_errors |
| 63 | #pragma pedantic |
| 64 | #pragma warn_deprecated |
| 65 | |
| 66 | #include <config.h> |
| 67 | #include <mail.h> |
| 68 | #include <wizlevels.h> |
| 69 | |
| 70 | // debugging |
| 71 | #define DEBUG(msg) if ( find_player("zesstra") ) \ |
| 72 | tell_object( find_player("zesstra"), "MAILER: "+msg ) |
| 73 | #undef DEBUG |
| 74 | #define DEBUG(x) |
| 75 | |
| 76 | // write out a message to the recipient |
| 77 | #define NOTIFY_RECIPIENT |
| 78 | // who gets undeliverable mail? |
| 79 | #define BOUNCE_ADDR "mud@mg.mud.de" |
| 80 | #define SECURITY(x) (geteuid(x) == ROOTID || geteuid(x) == MAILID) |
| 81 | // flag for _DeliverMail |
| 82 | #define MAIL_DELAYED 4096 |
| 83 | |
| 84 | // prototypes |
| 85 | protected void create(); |
| 86 | static int GetFolders( string user ); |
| 87 | static string _unify( string str ); |
| 88 | static string *unify( string *str ); |
| 89 | static string *expand( string *addr, int expa ); |
| 90 | static string _filter_addr( string addr ); |
| 91 | public string *DeliverMail( mixed msg, int expa ); |
| 92 | public int FingerMail( string user ); |
| 93 | static void save_msg( mixed msg, string user ); |
| 94 | public int RemoveMsg( int msg, int folder, string user ); |
| 95 | public int MoveMsg( int msg, int folder, string newfolder, string user ); |
| 96 | public int DeleteUnreadFolder( string user ); |
| 97 | public int RemoveFolder( string folder, string user ); |
| 98 | public int MakeFolder( string folder, string user ); |
| 99 | public int query_recipient_ok( string name ); |
| 100 | public void deliver_mail( string recipient, string from, string subject, |
| 101 | string mail_body ); |
| 102 | |
| 103 | |
| 104 | mixed *folders; /* used for save and restore of mail files */ |
| 105 | static mapping alias; |
| 106 | static string cachedname; /* whose folder is still in memory? */ |
| 107 | |
| 108 | |
| 109 | protected void create() |
| 110 | { |
| 111 | mixed tmp; |
| 112 | int i; |
| 113 | string s1, s2; |
| 114 | |
| 115 | seteuid(ROOTID); |
| 116 | alias=([]); |
| 117 | |
| 118 | if ( tmp = read_file("/mail/system.mailrc") ){ |
| 119 | tmp = explode( tmp, "\n" ); |
| 120 | |
| 121 | for ( i = sizeof(tmp); i--; ) |
| 122 | if ( sscanf( tmp[i], "%s %s", s1, s2 ) == 2 ) |
| 123 | alias[s1] = s2; |
| 124 | } |
| 125 | } |
| 126 | |
| 127 | |
| 128 | // GetFolders laedt einen folder, wenn er nicht im cache ist, und gibt |
| 129 | // 0 zurueck, wenn der folder nicht vorhanden oder evtl auch leer ist. |
| 130 | // Sinn: Vor allem bei Listenargumenten im mailer kann es leicht vorkommen, |
| 131 | // dass dasselbe mailfile einige Male hintereinander gebraucht wird. |
| 132 | |
| 133 | static int GetFolders( string user ) |
| 134 | { |
| 135 | if ( user == cachedname ){ |
| 136 | DEBUG( "Using cached folder for " + user + "\n" ); |
| 137 | return sizeof(folders[1]); |
| 138 | } |
| 139 | |
| 140 | cachedname = user; |
| 141 | |
| 142 | if ( !restore_object( MAILPATH + "/" + user[0..0] + "/" + user ) ){ |
| 143 | DEBUG( "Loading folder: " + user + " (empty)\n" ); |
| 144 | folders = ({ ({}), ({}) }); |
| 145 | return 0; |
| 146 | } |
| 147 | |
| 148 | DEBUG( "Loading folder:" + user + "\n" ); |
| 149 | return 1; |
| 150 | } |
| 151 | |
| 152 | |
| 153 | static string _unify( string str ) |
| 154 | { |
| 155 | return str[0] == '\\' ? str[1..] : str; |
| 156 | } |
| 157 | |
| 158 | |
| 159 | static string *unify( string *str ) |
| 160 | { |
| 161 | if ( !pointerp(str) ) |
| 162 | return ({}); |
| 163 | |
| 164 | str = map( filter( str, #'stringp/*'*/ ), #'lower_case/*'*/ ); |
| 165 | str = map( str, "_unify", this_object() ); |
| 166 | |
| 167 | return m_indices( mkmapping(str) ); |
| 168 | } |
| 169 | |
| 170 | |
| 171 | #define MG_NAMES ({ MUDNAME, "mg", "morgengrauen", "mud", "mg.mud.de" }) |
| 172 | |
| 173 | string expandSystemRecursive(string addr,int maxrec){ |
| 174 | string *list,*tlist; |
| 175 | string ret,tmp; |
| 176 | int i,size; |
| 177 | |
| 178 | if(maxrec>8 || !addr){ |
| 179 | return addr; |
| 180 | } |
| 181 | maxrec++; |
| 182 | |
| 183 | tlist=({}); |
| 184 | ret=""; |
| 185 | |
| 186 | list=explode(addr,","); |
| 187 | list-=({""}); |
| 188 | size=sizeof(list); |
| 189 | for(i=0;i<size;i++){ |
| 190 | if(tmp=alias[list[i]]){ |
| 191 | tlist+=explode(tmp,","); |
| 192 | } |
| 193 | else{ |
| 194 | tlist+=({list[i]}); |
| 195 | } |
| 196 | } |
| 197 | tlist-=({""}); |
| 198 | ret=implode(tlist,","); |
| 199 | |
| 200 | if((ret!=addr)!=0){ |
| 201 | ret=expandSystemRecursive(ret,maxrec); |
| 202 | } |
| 203 | return ret; |
| 204 | } |
| 205 | |
| 206 | // expa: also do alias and forward-expansion? (for inbound external mail) |
| 207 | // expa == 0 means full expansion, known flags are NO_SYSTEM_ALIASES |
| 208 | // and NO_USER_ALIASES |
| 209 | static string *expand( string *addr, int expa ) |
| 210 | { |
| 211 | string tmp, *new, *ret; |
| 212 | int i; |
| 213 | closure qf; |
| 214 | |
| 215 | ret = ({}); |
| 216 | addr -= ({""}); |
| 217 | qf = symbol_function( "QueryForward", FWSERV ); |
| 218 | |
| 219 | for ( i = sizeof(addr); i--; ){ |
| 220 | addr[i] = lower_case( addr[i] ); |
| 221 | // @morgengrauen-namen werden lokal zugestellt. |
| 222 | if ( sizeof(new = explode( addr[i], "@" )) == 2 && |
| 223 | member( MG_NAMES, new[1] ) != -1 ) |
| 224 | addr[i] = new[0]; |
| 225 | |
| 226 | if ( !(expa & NO_SYSTEM_ALIASES) && tmp = expandSystemRecursive(addr[i],0) ){ |
| 227 | ret += explode( tmp, "," ); |
| 228 | } |
| 229 | else |
| 230 | ret += ({ addr[i] }); |
| 231 | } |
| 232 | |
| 233 | for ( i = sizeof(ret); i--; ){ |
| 234 | if ( ret[i][0] == '\\' ) |
| 235 | ret[i] = ret[i][1..]; |
| 236 | else if ( !(expa & NO_USER_ALIASES) ) |
| 237 | ret = ret - ({ ret[i] }) + |
| 238 | explode( funcall( qf, ret[i] ), "," ); |
| 239 | } |
| 240 | |
| 241 | return ret; |
| 242 | } |
| 243 | |
| 244 | |
| 245 | static string _filter_addr( string addr ) |
| 246 | { |
| 247 | addr = regreplace( addr, "[^<]*<(.*)>[^>]*", "\\1", 0); |
| 248 | return regreplace( addr, " *([^ ][^ ]*).*", "\\1", 0); |
| 249 | } |
| 250 | |
| 251 | #ifdef INTERNET_MAIL_ENABLED |
| 252 | #define FOOTER \ |
| 253 | "\n*****************************************************************\n" \ |
| 254 | "* MorgenGrauen MailRelay v1.0 - Processed %s, %s *\n" \ |
| 255 | "* MorgenGrauen - mg.mud.de 23 - 87.79.24.60 23 *\n" \ |
| 256 | "*****************************************************************" |
| 257 | #endif |
| 258 | |
| 259 | public string *DeliverMail( mixed msg, int expa ) |
| 260 | { |
| 261 | string sender, *recipients, *recok, t, *tmp; |
| 262 | mixed *newmsg; |
| 263 | int i; |
| 264 | #ifdef INTERNET_MAIL_ENABLED |
| 265 | int ext; |
| 266 | #endif |
| 267 | |
| 268 | if ( !pointerp(msg) || sizeof(msg) != 9 ) |
| 269 | return 0; |
| 270 | |
| 271 | DEBUG( sprintf( "DeliverMail: %O %O\n", msg[0..4] +({0})+ msg[6..7], expa ) ); |
| 272 | t = ctime(time()); |
| 273 | |
| 274 | // Ohne Empfaenger wird abgebrochen |
| 275 | if (!stringp(msg[MSG_RECIPIENT])) |
| 276 | return 0; |
| 277 | |
| 278 | if ( !(expa & MAIL_DELAYED) ){ |
| 279 | /* determine the real sender */ |
| 280 | if ( extern_call() && object_name(previous_object())[0..7] != "/secure/" ) |
| 281 | sender = getuid( this_interactive() || previous_object() ); |
| 282 | else |
| 283 | sender = msg[MSG_SENDER]; |
| 284 | |
| 285 | /* make a list of all recipients */ |
| 286 | recipients = ({ msg[MSG_RECIPIENT] }); |
| 287 | |
| 288 | if ( !(expa & NO_CARBON_COPIES) ){ |
| 289 | if ( pointerp(msg[MSG_CC]) ) |
| 290 | recipients += msg[MSG_CC]; |
| 291 | |
| 292 | if ( pointerp(msg[MSG_BCC]) ) |
| 293 | recipients += msg[MSG_BCC]; |
| 294 | } |
| 295 | |
| 296 | // Mail-Aliase ersetzen |
| 297 | recipients = expand( recipients, expa ); |
| 298 | |
| 299 | // doppelte Adressen loeschen (nebenbei: auf Kleinschreibung wandeln) |
| 300 | recipients = unify( recipients ); |
| 301 | |
| 302 | // Realnamen und Kommentare entfernen |
| 303 | recipients = map( recipients, "_filter_addr", this_object() ); |
| 304 | |
| 305 | // auf ungueltige Zeichen checken |
| 306 | if ( sizeof(tmp = regexp( recipients, "^[-_.@a-z0-9]*$" )) |
| 307 | != sizeof(recipients) ){ |
| 308 | tmp = recipients - tmp; |
| 309 | |
| 310 | for ( i = sizeof(tmp); i--; ) |
| 311 | log_file( "MAIL_INVALID", sprintf( "%s: Mail von %O (%O) an " |
| 312 | "'%O'.\n", dtime(time()), |
| 313 | msg[MSG_FROM], |
| 314 | sender, tmp[i] ) ); |
| 315 | |
| 316 | recipients -= tmp; |
| 317 | } |
| 318 | |
| 319 | // check for valid Subject and Body |
| 320 | if (!stringp(msg[MSG_SUBJECT])) |
| 321 | msg[MSG_SUBJECT] = "(no subject given)"; |
| 322 | if (!stringp(msg[MSG_BODY])) |
| 323 | msg[MSG_BODY] = |
| 324 | "\n\nSorry - This mail was delivered without a mail body\n\n"; |
| 325 | |
| 326 | DEBUG( sprintf( "NEED TO DELIVER TO %O\n", recipients ) ); |
| 327 | |
| 328 | /* build the new message */ |
| 329 | newmsg = ({ msg[MSG_FROM], sender, msg[MSG_RECIPIENT], |
| 330 | msg[MSG_CC], "", msg[MSG_SUBJECT], |
| 331 | dtime(time()), MUDNAME + ":" + time(), |
| 332 | msg[MSG_BODY] }); |
| 333 | } |
| 334 | |
| 335 | /* Send it off ... */ |
| 336 | recok = ({ }); |
| 337 | |
| 338 | // ACHTUNG: durch expand() geaenderte Adressen werden zugestellt, |
| 339 | // aber durch /mail/mailer.c zusaetzlich als unzustellbar genannt! |
| 340 | |
| 341 | for ( i = sizeof(recipients); i-- /*&& get_eval_cost() > 500000*/; ){ |
| 342 | DEBUG( sprintf( "Begin delivering to %s. Evalcosts left: %d.\n", |
| 343 | recipients[i], get_eval_cost() ) ); |
| 344 | if ( member( recipients[i], '@' ) > 0 && |
| 345 | strstr( recipients[i], "daemon" ) < 0 ) { |
| 346 | string rec, mud; |
| 347 | |
| 348 | tmp = explode( recipients[i], "@" ); |
| 349 | mud = tmp[1]; |
| 350 | rec = tmp[0]; |
| 351 | sender = regreplace( sender, "@", "%", 1 ); |
| 352 | // Zustellung via Intermud-Mail an andere Muds. |
| 353 | if ( member( mud, '.' ) == -1 ) { |
| 354 | "/secure/udp_mail"->deliver_mail( rec, mud, sender, |
| 355 | msg[MSG_SUBJECT], |
| 356 | msg[MSG_BODY] ); |
| 357 | recok += ({ recipients[i] }); |
| 358 | } |
| 359 | #ifdef INTERNET_MAIL_ENABLED |
| 360 | // Zustellung in den Rest des Internets. |
| 361 | else { |
| 362 | ext = 1; |
| 363 | sender = explode( sender, "%" )[0]; |
| 364 | rec = explode( regreplace( rec, "@", "%", 1 ), "%" )[0]; |
| 365 | mud = explode( regreplace( mud, "@", "%", 1 ), "%" )[0]; |
| 366 | |
| 367 | write_file( sprintf( "/mail/outbound/%s.%d-%d-%d", |
| 368 | sender, time(), i, random(123456) ), |
| 369 | sprintf( "%s\n%s@%s\n" |
| 370 | "Subject: %s\n" |
| 371 | "X-MUD-From: %s\n" |
| 372 | "X-MUD-To: %s\n" |
| 373 | "X-MUD-Cc: %s\n" |
| 374 | "X-MU-Subject: %s\n\n", |
| 375 | sender, rec, mud, |
| 376 | msg[MSG_SUBJECT], |
| 377 | sender, recipients[0], |
| 378 | pointerp(msg[MSG_CC]) ? |
| 379 | implode( msg[MSG_CC], "," ) : "", |
| 380 | msg[MSG_SUBJECT] ) + msg[MSG_BODY] + |
| 381 | sprintf( FOOTER, t[4..10] + t[20..], t[11..18] ) |
| 382 | + "\n" ); |
| 383 | recok += ({ recipients[i] }); |
| 384 | } |
| 385 | #endif // INTERNET_MAIL_ENABLED |
| 386 | |
| 387 | } |
| 388 | else |
| 389 | if ( file_size( SAVEPATH + recipients[i][0..0] + "/" + |
| 390 | recipients[i] + ".o" ) >=0 ){ |
| 391 | save_msg( newmsg, recipients[i] ); |
| 392 | recok += ({ recipients[i] }); |
| 393 | } |
| 394 | else { |
| 395 | string *tmpmsg = copy(newmsg); |
| 396 | tmpmsg[MSG_BODY] = "--- Text der Mail geloescht. ---\n"; |
| 397 | write_file( sprintf( "/mail/outbound/postmaster.%d-%d", |
| 398 | time(), random(time()) ), |
| 399 | sprintf( "postmaster\n" + BOUNCE_ADDR + |
| 400 | "\nSubject: Undeliverable Mail\n%O\n", |
| 401 | tmpmsg) ); |
| 402 | } |
| 403 | DEBUG( sprintf( "End delivering to %s. Evalcosts left: %d.\n", |
| 404 | recipients[i], get_eval_cost() ) ); |
| 405 | } |
| 406 | #ifdef INTERNET_MAIL_ENABLED |
| 407 | if ( ext ) |
| 408 | send_udp( UDPSERV, 4123, "DELIVERMAIL" ); |
| 409 | #endif |
| 410 | return recok; |
| 411 | } |
| 412 | |
| 413 | |
| 414 | public int FingerMail( string user ) |
| 415 | { |
| 416 | int newfolder, i; |
| 417 | |
| 418 | //Zugriff beschraenken, Zahl der gelesenen Mails ist Privatsphaere |
| 419 | if (!objectp(this_interactive()) || !stringp(user) || !sizeof(user)) |
| 420 | return(-1); |
| 421 | if ((getuid(this_interactive())!=user) && |
| 422 | (process_call() || !ARCH_SECURITY)) return(-1); |
| 423 | |
| 424 | if ( !GetFolders(user) ) |
| 425 | return 0; |
| 426 | |
| 427 | if ( (newfolder = member(folders[0],"unread")) != -1 ) |
| 428 | return sizeof(folders[1][newfolder]); |
| 429 | |
| 430 | return 0; |
| 431 | } |
| 432 | |
| 433 | |
| 434 | static void save_msg( mixed msg, string user ) |
| 435 | { |
| 436 | int newfolder; |
| 437 | object p; |
| 438 | |
| 439 | GetFolders( user ); |
| 440 | |
| 441 | /* if folder 'unread' doesn't exist, create it */ |
| 442 | newfolder = member( folders[0], "unread"); |
| 443 | |
| 444 | if ( newfolder == -1 ){ |
| 445 | folders[0] += ({ "unread" }); |
| 446 | folders[1] += ({ ({ }) }); |
| 447 | newfolder = member( folders[0], "unread"); |
| 448 | } |
| 449 | |
| 450 | folders[1][newfolder] += ({ msg }); |
| 451 | save_object( MAILPATH + user[0..0] + "/" + user ); |
| 452 | #ifdef NOTIFY_RECIPIENT |
| 453 | if ( p = find_player(user) ) |
| 454 | tell_object( p, "Ein Postreiter ruft Dir aus einiger Entfernung zu, " |
| 455 | "dass Du neue Post hast!\n" ); |
| 456 | #endif |
| 457 | } |
| 458 | |
| 459 | |
| 460 | /* Remove a message from a folder */ |
| 461 | public int RemoveMsg( int msg, int folder, string user ) |
| 462 | { |
| 463 | if ( !SECURITY(previous_object()) ) |
| 464 | return -2; |
| 465 | |
| 466 | if ( !GetFolders(user) ) |
| 467 | return -1; /* No such folder */ |
| 468 | |
| 469 | if ( !pointerp(folders) || !pointerp(folders[0]) || |
| 470 | folder >= sizeof(folders[0]) ) |
| 471 | return -1; |
| 472 | |
| 473 | if ( msg < 0 || sizeof(folders[1][folder]) <= msg ) |
| 474 | return 0; /* No such msg */ |
| 475 | |
| 476 | folders[1][folder][msg..msg] = ({}); |
| 477 | |
| 478 | save_object( MAILPATH + user[0..0] + "/" + user ); |
| 479 | return 1; /* Success */ |
| 480 | } |
| 481 | |
| 482 | |
| 483 | /* Move message into another folder */ |
| 484 | public int MoveMsg( int msg, int folder, string newfolder, string user ) |
| 485 | { |
| 486 | int target; |
| 487 | |
| 488 | if ( !SECURITY(previous_object()) ) |
| 489 | return -2; |
| 490 | |
| 491 | if ( !GetFolders(user) ) |
| 492 | return -1; /* Source folder not found */ |
| 493 | |
| 494 | if ( !pointerp(folders) || !pointerp(folders[0]) || |
| 495 | folder >= sizeof(folders[0]) ) |
| 496 | return -1; |
| 497 | |
| 498 | if ( msg < 0 || sizeof(folders[1][folder]) <= msg ) |
| 499 | return 0; /* No such msg */ |
| 500 | |
| 501 | if ( (target = member(folders[0], newfolder)) == -1 ) |
| 502 | return -3; |
| 503 | |
| 504 | if ( target == folder ) |
| 505 | return 1; |
| 506 | |
| 507 | if ( !pointerp(folders[1][target]) ) |
| 508 | folders[1][target] = ({ folders[1][folder][msg] }); |
| 509 | else |
| 510 | folders[1][target] += ({ folders[1][folder][msg] }); |
| 511 | |
| 512 | return RemoveMsg( msg, folder, user ); |
| 513 | } |
| 514 | |
| 515 | |
| 516 | public int DeleteUnreadFolder( string user ) |
| 517 | { |
| 518 | int unread, newmail; |
| 519 | |
| 520 | if ( !SECURITY(previous_object()) ) |
| 521 | return -2; |
| 522 | |
| 523 | if ( !GetFolders(user) ) |
| 524 | return -1; /* Source folder not found */ |
| 525 | |
| 526 | if ( (unread = member( folders[0], "unread")) == -1 ) |
| 527 | return 0; |
| 528 | |
| 529 | if ( (newmail = member( folders[0], "newmail")) == -1 ){ |
| 530 | folders[0] += ({ "newmail" }); |
| 531 | folders[1] += ({({})}); |
| 532 | newmail = sizeof(folders[1]) - 1; |
| 533 | } |
| 534 | |
| 535 | if ( !pointerp(folders[1][newmail]) ) |
| 536 | folders[1][newmail] = ({}); |
| 537 | |
| 538 | if ( pointerp(folders[1][unread]) ) |
| 539 | folders[1][newmail] += folders[1][unread]; |
| 540 | |
| 541 | folders[0][unread..unread] = ({}); |
| 542 | folders[1][unread..unread] = ({}); |
| 543 | |
| 544 | save_object( MAILPATH + user[0..0] + "/" + user ); |
| 545 | return 0; |
| 546 | } |
| 547 | |
| 548 | |
| 549 | public int RemoveFolder( string folder, string user ) |
| 550 | { |
| 551 | int i; |
| 552 | |
| 553 | if ( !SECURITY(previous_object()) ) |
| 554 | return -2; |
| 555 | |
| 556 | if ( !GetFolders(user) ) |
| 557 | return -1; /* No such folder */ |
| 558 | |
| 559 | if ( (i = member( folders[0], folder)) == -1 ) |
| 560 | return -1; /* No such folder */ |
| 561 | |
| 562 | if ( sizeof(folders[1][i]) > 0 ) |
| 563 | return 0; /* Folder not empty */ |
| 564 | |
| 565 | folders[0][i..i] = ({}); |
| 566 | folders[1][i..i] = ({}); |
| 567 | |
| 568 | save_object( MAILPATH + user[0..0] + "/" + user ); |
| 569 | return 1; |
| 570 | } |
| 571 | |
| 572 | |
| 573 | public int MakeFolder( string folder, string user ) |
| 574 | { |
| 575 | if ( !SECURITY(previous_object()) ) |
| 576 | return -2; |
| 577 | |
| 578 | if ( !folder || !stringp(folder) ) |
| 579 | return -1; /* Huh ? */ |
| 580 | |
| 581 | if ( folder == "unread" ) |
| 582 | return 0; /* Folder exists virtually :) */ |
| 583 | |
| 584 | GetFolders( user ); |
| 585 | |
| 586 | if ( member( folders[0], folder) != -1 ) |
| 587 | return 0; /* Folder exists */ |
| 588 | |
| 589 | folders[0] = folders[0] + ({ folder }); |
| 590 | folders[1] = folders[1] + ({ ({}) }); |
| 591 | |
| 592 | save_object( MAILPATH + user[0..0] + "/" + user ); |
| 593 | return 1; |
| 594 | } |
| 595 | |
| 596 | |
| 597 | public int query_recipient_ok( string name ) |
| 598 | { |
| 599 | #if INTERNET_MAIL_ENABLED |
| 600 | return (file_size( "secure/save/" + name[0..0] + "/" + name + ".o" ) > 0 |
| 601 | || member( name, '%' ) > 0 || member( name, '@' ) > 0 ); |
| 602 | #else |
| 603 | // es darf zwar ein @ in der Adresse vorkommen, dahinter aber kein . mehr |
| 604 | // (dann ist es ne Mail via Intermud-Mail, nicht ins Internet). |
| 605 | string *tmp; |
| 606 | return (file_size( "secure/save/" + name[0..0] + "/" + name + ".o" ) > 0 |
| 607 | || member( name, '%' ) > 0 |
| 608 | || (sizeof(tmp=explode(name,"@")) == 2 && strstr(tmp[1],".") == -1)); |
| 609 | #endif |
| 610 | } |
| 611 | |
| 612 | |
| 613 | public void deliver_mail( |
| 614 | string recipient, /* the local players real name*/ |
| 615 | string from, /* A string depicting the sender */ |
| 616 | string subject, /* The mail subject/header */ |
| 617 | string mail_body /* The actual mail message */ ) |
| 618 | { |
| 619 | DEBUG( sprintf("DELIVER %O\n", |
| 620 | ({ from, from, recipient, ({}), ({}), subject, time() })) ); |
| 621 | |
| 622 | // Geloggt wird, wenn ein aufrufendes Objekt nicht sicher ist. |
| 623 | if (object_name(previous_object())[0..7]!="/secure/") |
| 624 | write_file("/secure/ARCH/DELIVER_MAIL", |
| 625 | sprintf("%s : Aufruf von /secure/mailer->deliver_mail()\n" |
| 626 | " Sender: %O Empfaenger: %O\n PO: %O TI: %O TP:%O\n\n", |
| 627 | ctime(time()),from, recipient, |
| 628 | previous_object(), this_interactive(), this_player())); |
| 629 | |
| 630 | DeliverMail( ({ from, from, recipient, ({}), ({}), subject, time(), |
| 631 | "EXTERNAL", mail_body }), 0 ); |
| 632 | } |