diff --git a/mail/send_mail.anubis b/mail/send_mail.anubis index cd70b95..2bff694 100644 --- a/mail/send_mail.anubis +++ b/mail/send_mail.anubis @@ -18,6 +18,7 @@ read system/data_io.anubis read system/logger.anubis read calexium_lib/net_services_protocols/logger_service.anubis +read calexium_lib/mail/send_mail_type.anubis read lexers/enhanced_status.anubis read smtp_server_extensions.anubis @@ -34,25 +35,23 @@ define Int _sendmail_time_out = 300. //5 minutes of timeout error, reply(Int code, String enhanced_status, List(String) lines). -public type Str_HostName: - str_host_name(String str). +public type Smtp_Recipient: + smtp_recipient(String email, //email address of the recipient + + Int nb_tries, + Int uid, //parameter used by handle_status (mail_uid) + Int uid2 //same (contact_id) + ). -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, //domain of the sender like "mail.calexium.com" - Str_Sender sender, //sender email address - Str_Recipient recipient, //recipient email address - List(Data_IO) mail_parts, //email to send - SmtpAuth auth, // - Str_UID mail_uid, + send_param( Str_HostName host_name, //domain of the sender like "mail.calexium.com" + Str_Sender sender, //sender email address + List(Data_IO) mail_parts, //all parts of the email to send + List(Smtp_Recipient) recipients, //recipient email address + SmtpAuth auth, // + Str_UID mail_uid, Int last_smtp_code //0 means it's the first time ). @@ -62,20 +61,23 @@ public type Send_Param: define Result(SmtpClientResult, One) sm_MAIL_FROM ( - RWStream conn, - Send_Param param, - SmtpClientSession sm_session, - (Int) -> One progress_report, - (LogLevel, String) -> One logger + RWStream conn, //TCP connection + Str_Sender sender, //email address of the sender + List(Data_IO) mail_parts, //all parts to send + Smtp_Recipient recipient, //contain email address and uid + SmtpClientSession sm_session, //smtp session + (Int) -> One progress_report, //don't know what it is for the moment + (LogLevel, String) -> One logger //logger ) = with enhanced_status = sm_session.enhanced_status, + since recipient is smtp_recipient(rcpt_address, try, uid, uid2), //send MAIL FROM - if send_mail_from(conn, param.sender.str, sm_session, _sendmail_time_out, logger) is + if send_mail_from(conn, 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 + if send_recipient(conn, rcpt_address, sm_session, _sendmail_time_out, logger) is { error(result) then error(result), ok(_) then @@ -84,18 +86,48 @@ define Result(SmtpClientResult, One) { 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) - } + if rewind(mail_parts) then + if send_content(conn, 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 "+sender.str+" TO "+rcpt_address); + ok(unique) + } + else + error(error) } } }. +define Result(SmtpClientResult, One) + send_to_recipients_list + ( + RWStream conn, //TCP connection + Send_Param param, + List(Smtp_Recipient) recipients, //recipients with email to send + SmtpClientSession sm_session, //smtp session + (Int) -> One progress_report, //don't know what it is for the moment + (LogLevel, String) -> One logger, //logger + (Result(SmtpClientResult, One), Smtp_Recipient) -> One handle_result + )= + if recipients is + { + [] then ok(unique), + [ rcpt . tail ] then + with result = sm_MAIL_FROM(conn, param.sender, param.mail_parts, rcpt, sm_session, progress_report, logger), + //here we apply the function provided by application to handle the result + handle_result(result, rcpt); + //if there is another recipient we send a RSET and we are able to send the + //email to the next recipient within the same smtp session + if length(tail) > 0 then + send_rset(conn, sm_session, _sendmail_time_out, logger); + send_to_recipients_list(conn, param, tail, sm_session, progress_report, logger, handle_result) + else + ok(unique) + } + . Apply the whole protocol: @@ -110,7 +142,8 @@ public define Result(SmtpClientResult, One) Send_Param param, (SmtpClientSession, Send_Param) -> Result(SmtpClientResult, Send_Param) prepare_mail_callback, (Int) -> One progress_report, - (LogLevel, String) -> One logger + (LogLevel, String) -> One logger, + (Result(SmtpClientResult, One), Smtp_Recipient) -> One handle_result ) = // // Our connection to the SMTP server is opened. We just have to apply the protocol. @@ -135,7 +168,10 @@ public define Result(SmtpClientResult, One) 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) + ok(new_param) then + with result = send_to_recipients_list(conn, new_param, new_param.recipients, sm_session, progress_report, logger, handle_result), + send_quit(conn, sm_session, _sendmail_time_out, logger); + result } } } @@ -154,13 +190,15 @@ public define Result(SmtpClientResult, One) RWStream conn, Send_Param param, (SmtpClientSession, Send_Param) -> Result(SmtpClientResult, Send_Param) prepare_mail_callback, + (Result(SmtpClientResult, One), Smtp_Recipient) -> One handle_result ) = 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) + else log(level, send_mail_log, txt), + handle_result ). public define Result(SmtpClientResult, One) @@ -168,10 +206,12 @@ public define Result(SmtpClientResult, One) ( RWStream conn, Send_Param param, + (Result(SmtpClientResult, One), Smtp_Recipient) -> One handle_result ) = send_mail(conn, param, - (SmtpClientSession sm_session, Send_Param param) |-> ok(param) + (SmtpClientSession sm_session, Send_Param param) |-> ok(param), + handle_result ). public define Result(SmtpClientResult, One) @@ -198,7 +238,7 @@ public define Result(SmtpClientResult, One) error(error), ok(server_conn) then - send_mail(server_conn, param), + send_mail(server_conn, param, (Result(SmtpClientResult, One) dum, Smtp_Recipient my) |-> unique), } }. diff --git a/mail/send_mail_type.anubis b/mail/send_mail_type.anubis index 0bd56ef..fc047f0 100644 --- a/mail/send_mail_type.anubis +++ b/mail/send_mail_type.anubis @@ -12,6 +12,18 @@ read tools/basis.anubis read calexium_lib/mail/smtp_client.anubis +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_Status: ready, //ready to send finished, //the mail is delivered correctly diff --git a/mail/smtp_client.anubis b/mail/smtp_client.anubis index 555fc31..95666c5 100644 --- a/mail/smtp_client.anubis +++ b/mail/smtp_client.anubis @@ -532,12 +532,16 @@ public define One ) = forget(smtp_send_command(conn, "QUIT", 221, session, timeout, logger)). -// if smtp_send_line(conn,"QUIT", logger) is -// { -// failure then logger(logWarning, "error sending QUIT"), -// success(_) then forget(receive_reply(conn, session.enhanced_status, timeout, logger)) -// }. - +public define One + send_rset + ( + RWStream conn, + SmtpClientSession session, + Int timeout, + (LogLevel, String) -> One logger + ) = + forget(smtp_send_command(conn, "RSET", 250, session, timeout, logger)). + define List(String) get_auth_method ( -- libgit2 0.21.4