cURL / Mailing Lists / curl-library / Single Mail

curl-library

Re: SMTP recipient issues

From: Rich Gray <rgray_at_plustechnologies.com>
Date: Sat, 16 Jun 2012 20:43:37 -0400

Dan wrote:
> Did we come to any sort of consensus about what the implementation should
> look like?

I must apologize for my lack of activity on this thread. I've simply been
hammered by work and domestic issues and will be for some time yet to come.
  I have been trying to follow it though and once again, would like to offer
an off the cuff comment or two, stating in advance that I haven't had any
opportunity to look at the source code or re-read the SMTP related RFCs.

The current problem here seems to be how to handle rejected e-mail
recipients. I agree that the current behavior of failing the SMTP send
operation if any recipient is rejected is probably the proper course of
action. I think that having the ability to do a send which completes even
if there are some bad addresses is also a very reasonable thing to want and
should be supported. But neither mode of operation seems reasonable to me
without some way to determine which address(es) failed. Internet nettiquete
demands that one shall prune one's address lists and not keep beating on
dead addresses!!

Stepping back slightly, SMTP might be one of the internet's nastiest
environments - Thank the Spammers! To avoid abuse, SMTP servers do all
kinds of things to shrug off badness. They may reject a client after
[E]HELO because it is in a blocklist. They may reject because of content in
the message data. There's all kinds of strange behavior servers can do
(above and beyond weird interpretations of SMTP.) Seem to me that any
client is going to have to be very flexible. Trying to handle variability
sanely in libcurl's SMTP module will probably drive everybody crazy. I fear
that design decisions now will make future adjustments/enhancements
difficult, by locking in the API.

I'm driven back to the notion of some sort of SMTP event callback, designed
to be extensible, is the way to go. It would allow the base libcurl/SMTP
modules to stay fairly simple, with complex behavior, if desired, handled
via the callback. If done right, the option for the SMTP event callback
would be the only option added to libcurl's main API. All further additions
can be encapsulated within the callback's API.

My suggestion for the SMTP event callback is to have it called with pointers
to an SMTP event struct and the userdata struct. If the event does nothing
to the event struct and returns 0, the SMTP module will do its default behavior.

The initial event would be for address failure. Items available via the
struct could be:
* the event code 1 - SMTP RCPT failure
* the failing address
* the SMTP failure code
* the text from the SMTP failure

Return codes could be
* 0 - continue trying addresses, but fail command(default)
* 1 - continue trying addresses, send if any addresses are OK
* 2 - fail immediately, try no further addresses

So, if all one wants to do is change to behavior 1 or 2, one need only
provide a callback routine which checks for the RCPT failure event and
returns with the desired code, else (other, future event code) returns with 0.

If an application wants to be aware of failed addresses, it can add them to
a list in userdata. If it wants to do its own logging, it has the info it
needs.

To support the ability of the application to process failures at other
points in the send operation, new event(s) can be added to expose the
failure information via the callback. Appropriate return codes and data in
the callback structure can influence how libcurl continues the operation.

If support for custom commands is desired, events could be added which would
be run prior to the normal command. Data set into the event structure
and/or return code could override default behavior. The struct could
contain the code and data for the command about to be run and the callback
could modify it or use the return code tell libcurl to do something
different. Events like this could also act as hooks for traces/logging by
the application.

If multiple events do get added, an event 0, initialize, could be added
which would be called prior to the beginning of the SMTP operation. It
could do things like set a mask for which events are desired or adjust
parameters (options) prior to the start of the protocol operations.

The point is that it should be possible to start simple and solve the
immediate RCPT problem with a fairly minimal callback. After doing so, it
is possible to have the freedom to add considerable flexibility to SMTP
operations while keeping the changes completely contained within the SMTP
module.

A couple of miscellaneous thoughts:

* VRFY is probably not worth it. It has been abused by the spammers to
probe for valid addresses. (Not that this can't be done anyway by starting
a normal MAIL transaction and quitting before actually sending DATA.)

* The RCPT problem is only likely to occur in local (non-Internet)
situations. If one is not delivering mail to the domain of the recipient,
most servers will have no way to verify the address; they will simply be
acting as relays and will store and forward. The wider application (or a
human) will have to deal with any resulting bounces. I think some servers
do verify that at least the target domain exists at RCPT time. Local stuff
(same domain) will most likely be the case where RCPT failures will occur,
because the server will know what users are valid, whether mailbox quotas
are exceed, etc.

Cheers!
Rich

-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html
Received on 2012-06-17