Question:
I’m seeing this error in the mailman.LastErrorText after trying to send email:
...
Socket is not ready for writing SocketError: WSAEWouldBlock
...
Also, how can I programmatically determine the cause of failure when sending email?
Answer:
The most common reasons for SMTP failure are:
1) Cannot connect to SMTP server.
2) Invalid logon credentials (i.e. the username and/or password is invalid)
3) SMTP 550 5.7.1 Unable to relay error
I’ll discuss each. The WSAEWouldBlock indicates a failure to establish a TCP/IP connection with the remote host at the given port. The Chilkat component is reporting back the error returned from the underlying Winsock function call. Internal to Chilkat, all TCP/IP socket communications are non-blocking, which gives Chilkat the ability to provide timeout properties and fire "heartbeat" events while waiting on a socket. (You’ll also see the WSAEWouldBlock error in all other Chilkat components that use TCP/IP sockets: FTP, HTTP, IMAP, etc.) Of course, you probably don’t want to programmatically parse the contents of LastErrorText, so how can you determine if the problem is connectivity? You can call mailman.VerifySmtpConnection.
The purpose of mailman.VerifySmtpConnection is to determine whether it is possible to establish a TCP/IP connection with the SMTP server, and nothing more. You might call this after any SMTP-related method fails. The reasons for connectivity failures include: (1) your general connectivity to the Internet is not working, (2) there is a firewall blocking the outbound port (usually 25), (3) an Anti-Virus or Anti-Spyware program is blocking the connection. In some cases you may wonder why Outlook works but your app doesn’t. It’s usually because Outlook is flagged as a "trusted" program in the eyes of the Anti-Virus program. Look for options to configure your Anti-Virus/Spyware to trust your app. (4) a firewall on the remote server is blocking inbound port 25 (or whatever port the SMTP server is using), (5) you have TCP/IP port filtering turned on and it is blocking the port (either at the client or server side).
Anyway, there are lots of reasons why connectivity may be disabled. Some are intermittent and some are permanent unless fixed.
If VerifySmtpConnection indicates that connectivity is good, you can then call mailman.VerifySmtpLogin to check the username/password. If it returns a failed status, then you know the problem is an invalid username and/or password.
Finally, you can check the mailman.LastSmtpStatus property (an integer). SMTP reply codes are defined in RFC 821 in a general way — but it lacks complete information. In fact, I don’t think a complete list of SMTP reply codes with accurate meanings exists anywhere on the Internet. They are vaguely defined. The most common one seems to be 550, and the most common reason for getting a 550 is "unable to relay". This means that you are trying to send email to a domain external to your SMTP server without authenticating. In most cases, you can send email to addresses with the same domain as the SMTP server without authenticating, assuming you’re connecting from a computer in the SMTP server’s local area network. If you try to use the SMTP server as a relay — you’ll be blocked unless you can provide a valid login/password (i.e. make sure you set the mailman.SmtpUsername and SmtpPassword properties). In some cases, you’ll find that an SMTP server allows you to send to external email addresses without authentication. This usually happens when you needed to authenticate to gain access to the local area network in the first place.. For example, right now I’m connected to the Internet via cable modem, and I can send email via my ISP’s SMTP server w/out authentication. It’s because authentication was initially required to logon to the network. Since I’ve already authenticated, I can send email via the cable company’s SMTP server without additional authentication. However, if I connect to mail.chilkatsoft.com and try to send email, I’ll need to authenticate in all cases because the connection originates from outside chilkatsoft.com. In a nutshell, if the LastSmtpStatus is 550, and the SmtpUsername and/or SmtpPassword properties are empty, or you see substrings such as "unable to relay" or "5.7.1″ in the LastErrorText, then you know it’s a case of needing to authenticate. The solution is to simply set the SmtpUsername/SmtpPassword properties to valid values. Note: if you are using NTLM authentication, you can set these properties to "default"/"default" and Chilkat will use the credentials of your current logged-on process. Also, Chilkat normally automatically chooses the best (most secure) authentication method. You don’t need to explicitly set the SmtpAuthMethod property except in special situations. It’s best to let Chilkat decide (because an SMTP server will provide a list of supported authentication methods to the SMTP client, allowing the client to choose one).
To summarize, when you get an SMTP failure check things in this order:
1) It’s quickest to first check the LastSmtpStatus because it requires no additional communications with the server. If you see a 550, …
2) Call VerifySmtpConnection to check the connection.
3) Call VerifySmtpLogin to check the login credentials.
Note: It doesn’t make sense to call VerifySmtpConnection and/or VerifySmtpLogin prior to calling SendEmail. Let’s say you called both Verify methods prior to calling SendEmail. That’s 3 connections created and destroyed for each email sent. It’s best to use these methods as a diagnostic after a failure — and that is why they were provided. Also, SendEmail and the other SMTP methods will continue to use the same SMTP session. The Verify methods cause the SMTP connections to be closed and re-established. It’s most efficient to operate in the same session as much as possible…