/* * Created by PyramIDE. * User: ricard * Date: 22/12/2008 * Time: 17:49 * */ read tools/basis.anubis read tools/connections.anubis read tools/printable_tree.anubis read network/dns.anubis read network/tools.anubis read system/files.anubis read system/string.anubis read system/data_io.anubis read system/logger.anubis read calexium_lib/net_services_protocols/logger_service.anubis read lexers/enhanced_status.anubis read smtp_server_extensions.anubis read authentication.anubis read smtp_client.anubis public define String send_mail_log = "SendMail". public define LogMask send_mail_mask = logMask("send_mail"). define Int _sendmail_time_out = 300. //5 minutes of timeout public type SendMailResult: ok, error, reply(Int code, String enhanced_status, List(String) lines). public type Str_HostName: str_host_name(String str). public type Str_Sender: str_sender(String str). public type Str_Recipient: str_recipient(String str). public type Str_UID: str_UID(String str). public type Send_Param: send_param( Str_HostName host_name, Str_Sender sender, Str_Recipient recipient, List(Data_IO) mail_parts, SmtpAuth auth, Str_UID mail_uid, Int last_smtp_code //0 means it's the first time ). define Result(SmtpClientResult, One) sm_MAIL_FROM ( RWStream conn, Send_Param param, SmtpClientSession sm_session, (Int) -> One progress_report, (LogLevel, String) -> One logger ) = with enhanced_status = sm_session.enhanced_status, //send MAIL FROM if send_mail_from(conn, param.sender.str, sm_session, _sendmail_time_out, logger) is { error(result) then error(result), ok(_) then //send RCPT TO if send_recipient(conn, param.recipient.str, sm_session, _sendmail_time_out, logger) is { error(result) then error(result), ok(_) then //send DATA if send_data(conn, sm_session, _sendmail_time_out, logger) is { error(result) then error(result), ok(_) then if send_content(conn, param.mail_parts, sm_session, _sendmail_time_out, progress_report, logger) is { error(result) then error(result), ok(_) then send_quit(conn, sm_session, _sendmail_time_out, logger); logger(logTrace, "SENT Mail FROM "+param.sender.str+" TO "+param.recipient.str); ok(unique) } } } }. Apply the whole protocol: // we can have a list of part file in param type. This can be very useful when we want // to send file as mailing. For the mailing, in each mail, only the header is different of the // other mails. The body part is the same. Then, the mailing sender can generate the header in one // file and keep the body in other file wich can be given to send_mail function as last file in the list public define Result(SmtpClientResult, One) send_mail ( RWStream conn, Send_Param param, (SmtpClientSession, Send_Param) -> Result(SmtpClientResult, Send_Param) prepare_mail_callback, (Int) -> One progress_report, (LogLevel, String) -> One logger ) = // // Our connection to the SMTP server is opened. We just have to apply the protocol. // if receive_reply(conn, false, _sendmail_time_out, logger) is { error then error(error), timeout then error(timeout), reply(code, status, lines) then if code = 220 then //send EHLO if send_ehlo(conn, param.host_name.str, _sendmail_time_out, logger) is { error(result) then error(result), ok(sm_session) then if do_auth(conn, param.auth, sm_session, _sendmail_time_out, logger) is { error(auth_result) then error(auth_result), ok(_) then if prepare_mail_callback(sm_session, param) is { error(prepare_result) then error(prepare_result), ok(new_param) then sm_MAIL_FROM(conn, new_param, sm_session, progress_report, logger) } } } else if code = 550 then //some server answer "550 5.7.1 Client host rejected: cannot find your reverse hostname, [88.181.64.17]" //before anything, then we try to extract the enhanced status if exists for relaying the mail with the ISP logger(logDebug, "Converting a 550 error for connection to a 432 error as distant server may be temporary overloaded."); error(reply(432, status, lines)) else error(reply(code, status, lines)) }. public define Result(SmtpClientResult, One) send_mail ( RWStream conn, Send_Param param, (SmtpClientSession, Send_Param) -> Result(SmtpClientResult, Send_Param) prepare_mail_callback, ) = send_mail(conn, param, prepare_mail_callback, (Int _) |-> unique, (LogLevel level, String txt) |-> if level is logTrace then logTrace(send_mail_log, send_mail_mask, txt) else log(level, send_mail_log, txt) ). public define Result(SmtpClientResult, One) send_mail ( RWStream conn, Send_Param param, ) = send_mail(conn, param, (SmtpClientSession sm_session, Send_Param param) |-> ok(param) ). public define Result(SmtpClientResult, One) send_mail ( String server, Word32 port, Send_Param param, )= if resolve_address(server) is { failure then logWarning(send_mail_log,"IP address NOT found for Mail server ["+server+"]"); error(error), success(ip_addr) then with ip_txt = ip_addr_to_string(ip_addr), logTrace(send_mail_log, send_mail_mask, "send_mail: Trying to connect to "+ip_txt); if (Result(NetworkConnectError,RWStream))connect(ip_addr, port) is { error(e) then logTrace(send_mail_log, send_mail_mask, "send_mail: Can't connect to "+ip_txt); error(error), ok(server_conn) then send_mail(server_conn, param), } }.