PHDEmail Component SMTP Object Interface

Last modified: 19 July 2001.

Home page
  • SMTP Object Interface
    Introduction
    Basic usage
    Errors
    Simple example
    Properties
    Methods
    Message Encoding
    Advanced methods
    Advanced example

  • Introduction

    The PHDSMTP object in the PHDEmail COM component lets you send emails using SMTP from an ASP script, Dynamic-CD GASP script, or any other COM programming language or container.

    Before using PHDSMTP, you must register the PHDEmail component, as described here.

    PHDSMTP sends an email message by talking to your SMTP server.  If a recipient is not on this server, your SMTP server relays the message towards or onto the recipient's server.  The recipient's server email software stores the email, ready to be read by the recipient when they next check for new mail.

    Note carefully that the PHDSMTP does not tell you if an email arrived successfully.  However, it will tell you whether it was sent off correctly.  SMTP server software usually sends a notification message back to the email sender if the message cannot be delivered.

    Freeware version

    The freeware version of PHDSMTP adds the following text to the bottom of each message sent:
    
    ----------------------------------------------------------
    Email sent using PHDEmail freeware, www.phdcc.com/phdemail
    

    Limitations

    PHDSMTP cannot send emails using a web based email service.  However emails can be sent to web based email addresses using a SMTP server.
    PHDSMTP cannot post messages to newsgroups.

    PHDSMTP currently cannot send file attachments.

    Technical information

    The PHDSMTP object interface Program ID is "PHDEmail.PHDSMTP".

    PHDEMail is an ANSI component, ie it works with 8-bit characters.  If you are running an application that sends non-ANSI characters to PHDEmail, then these will be received as question marks (?).

    See below for details of how message text is encoded.

    The Simple Mail Transport Protocol (SMTP) defines how emails are sent over the net.  SMTP was originally defined in RFC 821; the latest definition is in RFC 2821.  The email message format was originally defined in RFC 822; the latest definition is in RFC 2822.  Other RFCs define other aspects of message formatting.
    Note that other protocols, notably POP3 and IMAP, are used to retrieve emails from a holding server.


    Basic Usage

    Do not forget to register the PHDEmail component first.

    In your chosen programming environment, create an instance of the "PHDEmail.PHDSMTP" object.  Then set the RemoteHostName, Sender, Recipient, MessageSubject and MessageBody properties. Finally call the SendMail() method to send the message.

    THAT'S IT!  That's all you need to do to send a message.

    To send to multiple recipients, set Recipient to a comma-separated list of email addresses.  Or set the CC and BCC properties to similar lists of email addresses.

    Errors

    If SendMail() returns zero, then the email was sent successfully.  A negative number indicates an error detected by PHDEmail.  A number up to 599 is a response code returned by your SMTP server.  Finally, numbers greater than 10000 are communication errors, such as a timeout.  The file EmailErr.h in the development kit is a C++ header with definitions of the PHDEmail negative error values.

    The ErrorMsg read-only property contains a full description of the error.  The Response read-only property contains the last response line obtained from your SMTP server.  Finally the LastCommand read-only property stores the last command that PHDEmail sent to your SMTP server; this may help when tracking down errors.  Both Response and LastCommand may be empty strings.

    Note that SendMail() only ever makes one attempt to send an email.  It is up to you to retry later if you want to.

    Recipient validation

    As mentioned above, in most cases your SMTP server will not be able to tell you straight away whether a recipient is valid.  In this case, you will usually get a notification email telling you of the delivery problem.

    However, in some cases your SMTP server may be able to determine straight away if your recipients' email addresses are valid.  If they are invalid then it tells PHDEmail.

    By default, PHDEMail will not notify you of invalid recipients.  However if you set the IgnoreRecipientErrors property to False then SendMail() will return an error code if an invalid recipient is found.  The error number will probably be in the range 400-599.  LastCommand will contain "RCPT TO" followed by the email address in question.  Response will contain the message from your SMTP server, eg 550 Unable to relay for sales@phdcc.com.

    If none of the recipients are valid and IgnoreRecipientErrors property is True then SendMail() will fail, probably with response code 554 returned by the server in response to the last command "DATA" sent by PHDSMTP.

    Other SMTP errors

    Your SMTP server may perform other validation operations that could mean that your email is not sent.  For example, some may check that the Sender is permitted to use this server.  Other anti-spam email techniques may also be used.  Or message size restrictions may be enforced.  In most cases, your SMTP server's Response will indicate the cause of the problem.

    If you get timeout errors, then you might like to try increasing the values of the RecvTimeout and SendTimeout parameters.


    Simple ASP Example

    The following script function can be put in an .asp script and run in a suitable server, such as Microsoft IIS on the web, or PHD Dynamic-CD on a CD.

    The code first creates a "PHDEmail.PHDSMTP" object.  It then sets the RemoteHostName, Sender, Recipient, MessageSubject and MessageBody properties.  Finally it calls the SendMail() method to send the message.

    If SendMail() returns zero then the message has been sent OK.  If non-zero, then the script displays debugging information.  The ErrorMsg read-only property contains a full description of the error, and the Response read-only property contains the last response line received from your SMTP server. 

    Finally the SMTP variable is set to Nothing, releasing the PHDSMTP object.

    <%
    FUNCTION SendEmail
    
    SendEmail = False
    
    DIM SMTP
    On Error Resume Next
    SET SMTP = Server.CreateObject("PHDEmail.PHDSMTP")
    On Error Goto 0
    IF NOT isObject( SMTP) THEN
        Response.Write "Failed to create PHDEmail component object"
        EXIT FUNCTION
    end if
    
    SMTP.RemoteHostName = "mail.corp.com"
    SMTP.Sender = "user@corp.com"
    SMTP.Recipient = "sales@phdcc.com"
    SMTP.MessageSubject = "Test SendMail by PHDEmail"
    SMTP.MessageBody = "Hi PHD" & VbCrLf & "thanks for a useful component"
    
    Dim rv
    rv = SMTP.SendMail()
    If rv <> 0 Then
        Response.Write "SendMail failed "&CStr(rv)&" "&SMTP.ErrorMsg&"<P>"
        Response.Write "Last response: "&Server.HTMLEncode(SMTP.Response)&"<P>"
    Else
        Response.Write "Sent email OK<P>"
        SendEmail = True
    End If
    
    Set SMTP = Nothing
    
    END FUNCTION
    %>

    You can send to multiple recipients by listing the email addresses, comma-separated, in the Recipient property.  You can also send to one or more CC and BCC recipients by setting the BCC and CC properties in a similar way.


    C++ Example

    The PHDEmailTest program shows how to access the PHDEmail PHDSMTP object from C++.  The CSMTPTab class is defined in SMTPTab.cpp and SMTPTab.h.


    Properties

    Here is a complete list of the PHDEMail component PHDSMTP object properties.  Those listed in a yellow background are advanced parameters that are not normally used.

    Property
    name
    Type Description Example
    BCC String Comma-separated list of blind carbon copy recipients for the email. sales@phdcc.com,a@b.com
    CC String Comma-separated list of carbon copy recipients for the email. c@d.com
    ErrorMsg String
    read only
    A full description of the last error. PHDEmail: ConnectToRemoteHost Connection refused (10061)
    ForceQuotedPrintable Bolean
    True or False
    Set to True if you want to insist that Quoted-Printable encoding is used - see below. Default is False
    IgnoreRecipientErrors Bolean
    True or False
    Normally True so that an unrecognised recipient/CC/BCC does not stop an email being sent.  If False then an invalid recipient causes SendMail() or RCPT() to return straight away with the response code from your server. Default is True
    LastCommand String
    read only
    The last SMTP command that PHDSMTP sent to your SMTP server.  See the SMTP specifications for details of all SMTP commands. RCPT TO <sales@phdcc.com>
    MailPort Long The TCP/IP port of the SMTP server to contact. Default is 25
    MessageBody String The main text of the email.
    MessageSubject String The message subject.
    Recipient String Comma-separated list of recipients for the email. sales@phdcc.com
    RecvTimeout Long
    (seconds)
    The receive timeout in seconds. The default value is -1, ie:
    the "connect to host" time-out is 15 seconds.
    the "receive data" time-out is 10 seconds.
    Default is -1
    RemoteHostName String The domain name or IP address of the SMTP mail server to contact.
    Do not include www. in the domain name.
    mail.phdcc.com
    or
    192.168.0.1
    Response String
    read only
    The last response line sent by your SMTP server.  It usually consists of a three digit response code number followed by a text description.  The response may be several lines long, each line starting with a response code.  See the SMTP specifications for details of all SMTP responses. 221 2.0.0 Service closing transmission channel
    Sender String The email address of the sender. sales@phdcc.com
    SendTimeout Long
    (seconds)
    The send timeout in seconds. The default value is -1, ie:
    the "send data" time-out is 2 seconds.
    Default is -1


    Methods

    Here is a complete list of the PHDEMail component PHDSMTP object methods, ie functions.  Those listed in a yellow background are advanced methods that are not normally used.

    All methods set ErrorMsg and Response unless otherwise noted.

    Method
    name
    Parameters Return value Description
    CleanupConnection none None
    Does NOT set ErrorMsg or Response
    Closes the connection to the SMTP server cleanly.
    ConnectToRemoteHost none Long error code.
    Zero if OK.
    Attempts to connect to the SMTP server, with the domain name or IP address in RemoteHostName at the given MailPort.

    If this call succeeds, then you should call CleanupConnection() to close the connection cleanly.

    DATA none Long error code.
    Zero if OK.
    Sends the message text to the SMTP server.
    The message text starts with a header that includes the Recipient and CC email addresses (but not BCC) and the MessageSubject.  The message text then contains the MessageBody, possibly followed by the PHDEmail freeware text.  The text is encoded as described below.
    HELO none Long error code.
    Zero if OK.
    Starts an SMTP conversation.  Initially an "EHLO" command is tried.  If this fails, the "HELO" is tried.
    The SMTP server response is inspected by PHDSMTP to determine whether this server can accept 8BITMIME message data - see message encoding.

    If this call succeeds, then you should call QUIT() to stop the conversation and close the connection cleanly.

    MAIL none Long error code.
    Zero if OK.
    Sends the sending of a message, ie identifies the Sender to the SMTP server.

    If this call succeeds and a subsequent RCPT() or DATA() fails, then you should call SendCommand("RSET"+vbCrLf) before calling MAIL again.

    QUIT none Long error code.
    Zero if OK.
    Closes the SMTP conversation and SMTP connection.  There is no need to call CleanupConnection() after this.
    RCPT none Long error code.
    Zero if OK.
    Sends all Recipient, CC and BCC email addresses to the SMTP server as a series of "RCPT" commands.
    If IgnoreRecipientErrors is True then invalid recipients are ignored (ie response codes in the range 400-599).  If IgnoreRecipientErrors is False, an invalid recipient returns the response code to the caller of RCPT.  Use LastCommand to determine which email caused the problem.
    SendCommand String cmd Long response code. Sends a command string to the SMTP server and reads the response.  Do not forget to put CRLF (ie "\r\n" or vbCrLf) at the end of the command.

    Note that a response code is returned, ie zero is not normally returned.

    SendMail none Long error code.
    Zero if OK.
    Does the complete job of sending an email.  All relevant properties must be set beforehand.
    Does not retry if a mail send fails.


    Message Encoding

    A basic SMTP server only accepts 7-bit or 8-bit characters, with very limited line lengths, ie 76-80 characters.  Various Internet RFC standards have been defined over the years to overcome these restrictions to let us send whatever text and files we want in emails.  These standards specify how text and files should be encoded so that no information is lost.

    PHDSMTP does not currently support the full gamut of email encodings.  However it does support the two most common methods of sending text, 8BITMIME and Quoted-Printable.  8BITMIME is more efficient because it means that text does not have to be encoded.  The Quoted-Printable encoding ensures that text gets through even the oldest SMTP servers.

    PHDSMTP will use 8BITMIME if the SMTP server supports it.  The response to "EHLO" SMTP command tells PHDSMTP if the server supports 8BITMIME.  If the server does not support 8BITMIME (or if ForceQuotedPrintable is set True) then PHDSMTP sends the message text using the Quoted-Printable encoding.

    Note that there may still be line length limitations for 8BITMIME capable servers, eg 1000 characters.  If your text has very long lines, these may rejected, truncated or lost en-route.  If you think this may happen, then set ForceQuotedPrintable True to force use of Quoted-Printable.


    Advanced Methods

    The SendMail() method is sufficient for most users.  However if you want fine-grain control of SMTP interactions then PHDSMTP makes available a series of advanced methods.

    There are several methods that perform specific jobs in the mail sending process.  However there is one method, SendCommand(), that is used to send any command to the SMTP server.

    You should read the SMTP specifications carefully before using the advanced SMTP methods.  SMTP commands have to be sent in a specific order.  You should not be able to crash either the current computer or the SMTP server.

    Mail sending command

    A call of SendMail() is equivalent to the following series of calls (with various error situations handled correctly):
    1. ConnectToRemoteHost()
    2. HELO()
    3. MAIL()
    4. RCPT()
    5. DATA()
    6. QUIT()

    The advanced ASP example below simulates a call to SendMail() by following these steps.

    Cleanup methods

    You should call the appropriate methods to clean up your SMTP conversation if it goes wrong.

    If ConnectToRemoteHost() succeeds then you should call CleanupConnection() to close the connection cleanly.

    If HELO() succeeds then you should call QUIT() to stop the conversation and close the connection cleanly.  QUIT() closes the connection, so there is no need to call CleanupConnection() as well.

    If MAIL() succeeds, but a subsequent RCPT() or DATA() fails, then you should issue the "RSET" command before issuing another MAIL().  Use SendCommand() to issue the "RSET", eg SendCommand("RSET"+vbCrLf)

    Other SMTP commands

    The SendCommand() method lets you send any command you want to the SMTP server and read back the response.  SendCommand() must be passed a string that ends in CRLF, ie "\r\n" in C/C++ or vbCrLf in ASP or VB.

    Note that SendCommand() is not suitable for sending all types of command because commands such as "MAIL" require a series of interactions with the server.

    SendCommand() is useful for sending unusual SMTP commands such as "EXPN", "HELP", "NOOP", "RSET" and "VRFY".


    Advanced ASP Example

    This example shows how to call the individual PHDSMTP methods to issue an email, ie roughly equivalent to SendMail().

    <%
    FUNCTION SendEmail
    
    SendEmail = False
    
    DIM SMTP
    On Error Resume Next
    SET SMTP = Server.CreateObject("PHDEmail.PHDSMTP")
    On Error Goto 0
    IF NOT isObject( SMTP) THEN
        Response.Write "Failed to create PHDEmail component object"
        Exit Function
    end if
    
    SMTP.RemoteHostName = "mail.corp.com"
    
    rv = SMTP.ConnectToRemoteHost()
    If rv <> 0 Then
        Response.Write "Could not connect to SMTP server "&CStr(rv)
        Set SMTP = Nothing
        Exit Function
    End If
    Response.Write "ConnectToRemoteHost OK: <PRE>"&Server.HTMLEncode(SMTP.Response)&"</PRE><P>"
    
    rv = SMTP.SendCommand("HELP"+vbCrLf)
    If rv<200 or rv>299 Then
        SMTP.CleanupConnection()
        Response.Write "SendCommand failed "&CStr(rv)
            &"<BR>Response: "&SMTP.Response&"<BR>Last command: "&SMTP.LastCommand
        Set SMTP = Nothing
        Exit Function
    end if
    Response.Write "SendCommand HELP OK: <PRE>"&Server.HTMLEncode(SMTP.Response)&"</PRE><P>"
    
    rv = SMTP.HELO()
    If rv <> 0 Then
        SMTP.CleanupConnection()
        Response.Write "HELO failed "&CStr(rv)
            &"<BR>Response: "&SMTP.Response&"<BR>Last command: "&SMTP.LastCommand
        Set SMTP = Nothing
        Exit Function
    end if
    Response.Write "HELO OK: <PRE>"&Server.HTMLEncode(SMTP.Response)&"</PRE><P>"
    
    SMTP.Sender = "sales@phdcc.com"
    
    rv = SMTP.MAIL()
    If rv <> 0 Then
        Response.Write "MAIL failed "&CStr(rv)
            &"<BR>Response: "&SMTP.Response&"<BR>Last command: "&SMTP.LastCommand
        SMTP.QUIT()
        Set SMTP = Nothing
        EXIT SUB
    end if
    Response.Write "MAIL OK: <PRE>"&Server.HTMLEncode(SMTP.Response)&"</PRE><P>"
    
    SMTP.Recipient = "sales@phdcc.com"
    
    rv = SMTP.RCPT()
    If rv <> 0 Then
        Response.Write "RCPT failed "&CStr(rv)
            &"<BR>Response: "&SMTP.Response&"<BR>Last command: "&SMTP.LastCommand
        SMTP.QUIT()
        Set SMTP = Nothing
        Exit Function
    end if
    Response.Write "RCPT OK: <PRE>"&Server.HTMLEncode(SMTP.Response)&"</PRE><P>"
    
    SMTP.MessageSubject = "Test SendMail by PHDEmail"
    SMTP.MessageBody = "Hi PHD" & VbCrLf & "thanks for a useful component"
    
    rv = SMTP.DATA()
    If rv <> 0 Then
        Response.Write "DATA failed "&CStr(rv)
            &"<BR>Response: "&SMTP.Response&"<BR>Last command: "&SMTP.LastCommand
        SMTP.QUIT()
        Set SMTP = Nothing
        Exit Function
    end if
    Response.Write "DATA OK: <PRE>"&Server.HTMLEncode(SMTP.Response)&"</PRE><P>"
    
    rv = SMTP.QUIT()
    If rv <> 0 Then
        Response.Write "QUIT failed "&CStr(rv)
            &"<BR>Response: "&SMTP.Response&"<BR>Last command: "&SMTP.LastCommand
        SMTP.CleanupConnection()
        Set SMTP = Nothing
        Exit Function
    end if
    Response.Write "QUIT OK: <PRE>"&Server.HTMLEncode(SMTP.Response)&"</PRE><P>"
    
    Set SMTP = Nothing
    
    SendEmail = True
    
    END FUNCTION
    %>


    PHDEmail online