|
The Simple Mail Transfer Protocol (SMTP) enables applications to
deliver e-mail messages to one or more recipients. The library
provides an API for addressing and delivering messages, and
extended features such as user authentication and delivery status
notification. This library is typically used in conjunction with
the Mail Message library to create the messages, and the Domain
Name Service library to determine what servers are responsible for
accepting mail for a specific user.
Mail Exchanges
When a message is delivered to a user, the application must
determine what mail server is responsible for accepting messages
for that user. This can be accomplished using the Domain Name
Services (DNS) protocol, a protocol that is most commonly used to
resolve host names such as www.microsoft.com into Internet
addresses. This is typically accomplished by sending a request to a
nameserver, a computer system that provides domain name services.
In addition to resolving host names, nameservers can also provide
information about those servers which are responsible for accepting
mail for a given domain. There can be multiple servers which
process mail for a domain with each server assigned a priority as
part of their mail exchange (MX) record. If there is no mail
exchange record for a domain, then the domain name itself is
used.
To deliver a message directly to the recipient, you must examine
the recipient address and request the list of mail exchanges for
that user's domain. Using the DNS API, this is done by calling the
DnsEnumMailExchanges function. If the recipient address is
joe@bigcorp.com, you would want to enumerate the mail exchanges for
the bigcorp.com domain. This will give you the name of the servers
that will accept mail for users in that domain. For example, the
function may return the host name mail.bigcorp.com as the name of
the server which will accept mail for users in the bigcorp.com
domain. Note that it is possible that one or more of the mail
exchanges for a domain may not be in the recipient domain itself.
In other words, it is possible that smtp.othercorp.net could be
returned as a mail exchange for bigcorp.com. This is frequently the
case when another organization is forwarding mail for that
domain.
Therefore, there are three general steps that you must take when
delivering mail directly to the recipient:
- Parse the address of each recipient in the message. If you are
using the MIME API, the MimeEnumMessageRecipients function can be
helpful in extracting all of the recipient addresses. Everything
after the atsign (@) in the address is the domain portion of that
address.
- Perform an MX record lookup using the DNS API function
DnsEnumMailExchanges and specifying the recipient's domain. The
function will return the name of the servers responsible for
accepting mail for that user. If there are more than one server,
they will be returned in order of their relative priority, with the
highest priority server being returned first. This means that you
should attempt to connect to those servers in the order that they
are returned by the function.
- Attempt to connect to the first server returned by the
DnsEnumMailExchanges function. The connection should be on the
default port, and you should not attempt to use any authentication.
If the server accepts the connection, then use the SmtpSendMessage
function to deliver the message. If the connection is rejected or
the message is not accepted, attempt to connect to the next mail
exchange server until all servers have been tried.
- If no mail exchange servers were returned by
DnsEnumMailExchanges, or you could not connect to any of them,
attempt to connect to the domain specified in the address using the
default port. If the connection succeeds, then deliver the message.
If you cannot connect or the message is not accepted, then report
to the user that the message could not be delivered.
One last important consideration is that many Internet Service
Providers now block outbound connections on port 25 to any mail
servers other than their own. If you are unable to establish any
connections, either with the error that the connection was refused
or it consistently times out, contact your ISP to determine if port
25 is being blocked as an anti-spam measure. If this is the case,
it will be required that you relay all messages through their mail
servers.
Relay Servers
In some situations it may not be possible to send mail directly
to the server that accepts mail for a given domain. The two most
common situations are corporate networks which have centralized
servers that are responsible for delivering and forwarding
messages, or an Internet Service Provider (ISP) which specifically
blocks access to all mail servers other than their own. This is
usually done as either a security measure or as a means to inhibit
users from sending unsolicited commercial e-mail messages. If the
standard SMTP port is being blocked, then any connection attempts
will either fail immediately with an error that the server is
unreachable, or the connections will simply time-out. In either
case, a relay server must be specified in order to send e-mail
messages.
A relay server is a system which will accept messages addressed
to users who may be in a different domain, and will relay those
messages to the appropriate server that does accept mail for the
domain. Using a relay server is generally easier than sending
messages directly to the recipient. In order to send a message
through a relay, you need to perform the following steps:
- Connect to the relay server as you would normally.
- Authenticate the client to the server. This may or may not be
required, depending on how the server is configured. Some servers
may be configured to only require authentication if you are
connecting from an IP address that is not recognized as part of
that system's network, for example, if you are connecting using a
different Internet Service Provider. Others may always require
authentication. Check with the server administrator if necessary to
determine if and when authentication is required.
- Use the SmtpSendMessage function to deliver the message to the
recipients through the relay server. If there are multiple
recipients, you can use the MIME API to enumerate the recipient
addresses and then pass them to the SmtpSendMessage function.
It is important to note that using a mail server as a relay
without the permission of the organization or individual who owns
that server may violate Acceptable Use Policies and/or Terms of
Service agreements with your service provider. Systems which relay
messages from anyone, regardless of whether the message is coming
from a recognized domain, are called open relays. Because open
relays are often used to send unsolicited e-mail, many
administrators block mail that comes from one. It is recommended
that users check with their network administrators or Internet
service providers to determine if access to external mail servers
is restricted and what is the acceptable use policy for relaying
messages through their mail servers.
The first step your application must take is to initialize the
library, then establish a connection to the server and authenticate
the client if necessary. The following functions are available for
use by your application:
SmtpInitialize
Initialize the library and load the Windows Sockets library for the
current process. This must be the first function call that the
application makes before calling the other SMTP API functions.
SmtpConnect
Establish a connection to the SMTP server. This function will
return a handle to a client session which is used in subsequent
calls to the SMTP API.
SmtpAuthenticate
Authenticate yourself to the server using a username and password.
This function should be called immediately after the connection has
been established to the server. This is typically required if you
are attempting to use the mail server as a relay, asking it to
forward the message on to the server that actually accepts email
for the recipient. Many Internet Service Providers (ISPs) require
that users authenticate prior to sending mail through their
servers. You may need to contact the server administrator to
determine if authentication is required.
SmtpDisconnect
Disconnect from the SMTP server and release any resources that have
been allocated for the client session. After this function is
called, the client handle is no longer valid.
SmtpUninitialize
Unload the Windows Sockets library and release any resources that
have been allocated for the current process. This is the last
function call the application should make prior to terminating.
Message Delivery
There are two general methods that can be used to deliver
messages through the mail server. In most cases, it can be done
with a single function call. However, there are some circumstances
where it would be more appropriate to perform the transaction in
stages. The SMTP API supports both methods.
SmtpSendMessage
This is the simplest method for sending an email message through
the server. You provide the sender and recipient addresses, along
with the message contents and the function will submit the message
to the server for delivery.
SmtpCreateMessage
This function begins a transaction in which a message is
dynamically composed, addressed and delivered in stages. You
provide the sender address and message size to this function, and
after it returns you begin the next stage, which is addressing the
message.
SmtpAddRecipient
This function adds a recipient address to the recipient list for
the message. This should be called once for each recipient, as well
as for any recipients who are to receive "blind copies" of the
message. A blind copy is when the message is sent to a recipient,
but that recipient's address is not listed in any of the headers of
the message; the other recipients will be unaware that the message
was delivered to him. Most servers have a limit of approximately
100 recipients per message. It is possible that this function will
return an error for a specific recipient address; the address may
be malformed or it may not be acceptable for some other reason.
This does not mean that the message will be rejected in its
entirety, only that the specified recipient is not acceptable.
SmtpAppendMessage
This function should be called after all of the recipients have
been added. It is used to send the contents of the message to the
server. It is also possible to use the lower level SmtpWrite
function to send data directly to the server, however
SmtpAppendMessage is generally easier to use and can write data
from memory, the system clipboard or from a file on disk.
SmtpCloseMessage
This function is called after the entire message has been sent to
the server. This terminates the transaction and the message is
submitted for delivery. Note that it is possible for the server to
accept the message up to this point and then reject it at this
final step due to some restriction, such as the message being too
large.
|