7. Working with mails

7.1. Sending e-mail

AWS provides a complete API for sending e-mail using the SMTP protocol. You need to have access to an SMTP server to use this feature. The API covers sending simple mail with text message and/or with MIME attachments (base64 encoded). Here are the steps to send a simple e-mail:

  • Initialize the SMTP server (non secure)

    SMTP_Server : SMTP.Receiver :=
                    SMTP.Client.Initialize ("smtp.hostname");
    

    Here AWS uses the default SMTP port to create an SMTP mail server but it is possible to specify a different one. The hostname specified must be a valid SMTP server.

  • Initialize the SMTP server secure and with authentication

    Auth      : aliased constant SMTP.Authentication.Plain.Credential :=
                  SMTP.Authentication.Plain.Initialize
                    ("SMTP_Login", "SMTP_Password");
    
    SMTP_Server : SMTP.Receiver :=
                    SMTP.Client.Initialize
                      (Server_Name => "smtp.hostname",
                       Port        => 587,
                       Security    => SMTP.STARTTLS,
                       Credential  => Auth'Unchecked_Access);
    
  • Send the e-mail

    To send an e-mail there are many different APIs. Let’s send a simple text mail:

    Status : SMTP.Status;
    
    SMTP.Client.Send
      (SMTP_Server,
       From    => SMTP.E_Mail ("Pascal Obry", "pascal@obry.net"),
       To      => SMTP.E_Mail ("John Doe", "john.doe@here.com"),
       Subject => "About AWS SMTP protocol",
       Message => "AWS can send mails",
       Status  => Status);
    

    Here Status will contain the SMTP returned status.

  • Check that everything is ok

    Using the Status data it is possible to check whether the message was or wasn’t sent by the server. The status contains a code and an error message, both of them can be retrieved using specific routines, see AWS.SMTP. It is also possible to check that the call was successful with the SMTP.Is_Ok routine:

    if not SMTP.Is_Ok (Status) then
       Put_Line ("Can't send message: " & SMTP.Status_Message (Status));
    end if;
    

In the above example, the message content was given as a string but it is possible to specify a disk file. AWS can also send MIME messages either from disk files or with in memory base64 encoded binary data. The API also provides a way to send messages to multiple recipients at the same time and to send messages with alternative content (text and HTML for example). These features are not described here, complete documentation for the specification can be found at AWS.SMTP and AWS.SMTP.Client.

7.2. Retrieving e-mail

AWS provides an API to retrieve e-mails from a POP mailbox. POP stands for Post Office Protocol and is the main protocol used by Internet Service Providers around the world. IMAP is another well known protocol in this area but it is not supported by AWS.

We describes here the POP API. For a complete description see AWS.POP.

  • Opening the mailbox

    The first step is to authenticate using a user name and password. AWS supports two methods one called Clear_Text which is the most used and another one APOP which is more secure but typically not supported by ISP at this time (and will probably never be supported as a more secure protocol named SPA -Secure Password Authentication- could be used instead):

    Mailbox : POP.Mailbox :=
                POP.Initialize ("pop.hostname", "john.does", "mysuperpwd");
    

    The default Authentication method is Clear_Text.

  • Getting mailbox information

    When the connection is opened it is possible to get information about the mailbox like the number of messages or the total number of bytes in the mailbox:

    N     : constant Natural := POP.Message_Count (Mailbox);
    
    Bytes : constant Natural := POP.Size (Mailbox);
    
  • Retreiving individual e-mails

    Each message is numbered starting from 1. A function named Get will return a message given its mailbox’s number:

    Message : constant POP.Message := POP.Get (Mailbox, 2, Remove => True);
    

    Remove can be set to False for the message to stay on the mailbox. The default value is False.

  • Iterating through the mailbox content

    Another way to retreive message is by using an iterator:

    procedure Print_Subject
      (Message : in     POP.Message
       Index   : in     Positive;
       Quit    : in out Boolean) is
    begin
     Text_IO.Put_Line (POP.Subject (Message));
    end Print_Message;
    
    procedure Print_All_Subjects is new POP.For_Every_Message (Print_Subject);
    
    ...
    
    Print_All_Subjects (Mailbox, Remove => True);
    

    There exist a set of routines on a POP.Message object to get the subject the content, the date or any headers. It is also possible to work with attachments. See point below.

  • Working with attachments

    A message can have a set of MIME attachments. The number of attachments can be retrieved using Attachment_Count:

    Message : constant POP.Message := ...;
    
    A_Count : constant Natural := POP.Attachment_Count (Message);
    

    As for messages it is possible to get a single attachment using its index in the message or by using an iterator:

    First_Attachment : constant POP.Attachment := POP.Get (Message, 1);
    
    procedure Write_Attachment
      (Attachment : in     POP.Attachment
       Index      : in     Positive;
       Quit       : in out Boolean) is
    begin
       POP.Write (Attachment, Directory => ".");
    end Print_Message;
    
    procedure Write_All_Attachments is
      new POP.For_Every_Attachment (Write_Attachment);
    
    ...
    
    Write_All_Attachments (Message);
    

    It is also possible to retrieve the attachment’s filename and the content as a memory stream. See AWS.POP.

  • Closing the connection

    POP.Close (POP_Server);