in 1 minute check.. MAIL SOCKET MANAGEMENT count number of mail connections (miscconn[user].sock!=-1 && miscconn[user].type==2) if less than MAX_MAIL_CONNECTIONS while ((count_current_mail_connections < MAX_MAIL_CONNECTIONS) && (tries <= 2)) find free mail slot if there is one do_mail_connect() if bad connect, increase tries, continue through while if good, tries = 0 if not ABORT if not less than MAIL_CONNECTIONS or over # of tries ABORT MAIL CONNECTION MANAGEMENT: if (do_smtp_mail) { do directory read of maildir/outgoing/ counting (need_connections) up to MAX_MISC_CONNECTS; in main while() loop.. if socket readable get input if (stage==0 && input contains banner) stage=1 ready=1 if (stage==1 && input contains good helo reply) stage=2 ready=1 if (stage==2 && input contains good sender reply) stage=3 ready=1 if (stage==3 && input contains good recipient reply) stage=4 ready=1 if (stage==4 && input contains good DATA reply) stage=5 ready=1 if (stage==5 && input contains good message reply) stage=2 ready=1 remove queue file reset file fd,queuename continue through readacble sockets if socket writeable if (ready) { if (stage==1) { write helo ready=0 } if (stage==2) { readdir outgoing/ for first queue file if no queue file exists, close connection, continue; else rename/move first queue file to outgoing_active/ fopen queue file fd=FILEHANDLE queuename=FILENAME read first line write out sender if write fails close file move queuename back to outgoing/ close connection ready=0; } if (stage==3) { read next line write out recipient if write fails close file move queuename back to outgoing/ close connection ready=0; } if (stage==4) { write out "DATA" if write fails close file move queuename back to outgoing/ close connection ready=0; } if (stage==5) { reading next line from file write out body line if write fails close file move queuename back to outgoing/ close connection else loop read/write till end ready=0; } } MAIL COMPOSITION FILE *get_mailqueue_file(void) { time_t tm; int subtime=0; static FILE *tfp; tm=time(0); sprintf(filename,"%s/%s%ld.%d",OUTGOING_MAILDIR,(long)tm,subtime); while ((tfp=fopen(filename,"r")) && subtime != 100) { fclose(tfp); subtime++; sprintf(filename,"%ld.%d",(long)tm,subtime); } if (subtime==100) { write_log(ERRORLOG,YESTIME,"Could not open a new queue file in fmail()\n"); return NULL; } else { if (!(tfp=fopen(filename,"w"))) { write_log(ERRORLOG,YESTIME,"Could not open the new queue file %s in fmail() \n",filename); return NULL; } else return tfp; } return NULL; } if (!(wfp=get_mailqueue_file())) { error } fprintf(wfp,"%s\n",SYSTEM_EMAIL); fprintf(wfp,"%s\n",mail_addr); /* start body */ fclose(wfp); SMTP CONVERSATION: 220 stevenjude2.compustrat.com ESMTP Postfix HELO stevenjude2.compustrat.com 250 stevenjude2.compustrat.com MAIL FROM: joe@blow.com 250 Ok RCPT TO: receiver@blow.com 250 Ok DATA 354 End data with . BAD HELO: HELO 501 Syntax: HELO hostname BAD FROM: MAIL FROM: 500 Error: bad syntax BAD RCPT: RCPT TO: 501 Syntax: RCPT TO:
FUNCTIONS: void check_smtp(void); int do_smtp_connect(void); FILE *get_mailqueue_file(void); int queuetoactive_smtp(int user); int write_smtp_data(int user, int type); void requeue_smtp(int user); void check_misc_connects(void); int find_queue_slot(char *inpstr); ERROR/FAILURE/SUCCESS CODES: 211 System status, or system help reply 214 Help message [Information on how to use the receiver or the meaning of a particular non-standard command; this reply is useful only to the human user] 220 Service ready 221 Service closing transmission channel 250 Requested mail action okay, completed 251 User not local; will forward to 354 Start mail input; end with . 421 Service not available, closing transmission channel [This may be a reply to any command if the service knows it must shut down] 450 Requested mail action not taken: mailbox unavailable [E.g., mailbox busy] 451 Requested action aborted: local error in processing 452 Requested action not taken: insufficient system storage 500 Syntax error, command unrecognized [This may include errors such as command line too long] 501 Syntax error in parameters or arguments 502 Command not implemented 503 Bad sequence of commands 504 Command parameter not implemented 550 Requested action not taken: mailbox unavailable [E.g., mailbox not found, no access] 551 User not local; please try 552 Requested mail action aborted: exceeded storage allocation 553 Requested action not taken: mailbox name not allowed [E.g., mailbox syntax incorrect] 554 Transaction failed COMMAND-REPLY SEQUENCES: "P" = preliminary "I" = intermediate "S" = success "F" = failure "E" = error CONNECTION ESTABLISHMENT S: 220 F: 421 HELO S: 250 E: 500, 501, 504, 421 MAIL S: 250 F: 552, 451, 452 E: 500, 501, 421 RCPT S: 250, 251 F: 550, 551, 552, 553, 450, 451, 452 E: 500, 501, 503, 421 DATA I: 354 -> data -> S: 250 F: 552, 554, 451, 452 F: 451, 554 E: 500, 501, 503, 421 RSET S: 250 E: 500, 501, 504, 421 SEND S: 250 F: 552, 451, 452 E: 500, 501, 502, 421 SOML S: 250 F: 552, 451, 452 E: 500, 501, 502, 421 SAML S: 250 F: 552, 451, 452 E: 500, 501, 502, 421 VRFY S: 250, 251 F: 550, 551, 553 E: 500, 501, 502, 504, 421 EXPN S: 250 F: 550 E: 500, 501, 502, 504, 421 HELP S: 211, 214 E: 500, 501, 502, 504, 421 NOOP S: 250 E: 500, 421 QUIT S: 221 E: 500 TURN S: 250 F: 502 E: 500, 503