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

Reply via email to