Distributed James Server — Delivery Submission Notifications
DSN introduced in RFC-3461 allows a SMTP sender to demand status messages,
defined in RFC-3464 to be sent back to the Return-Path
upon delivery
progress.
DSN support is not enabled by default, as it needs specific configuration of the mailetcontainer.xml to be specification compliant.
To enable it you need to:
-
Add DSN SMTP hooks as part of the SMTP server stack
-
Configure mailetcontainer.xml to generate DSN bounces when needed
Enabling DSN in SMTP server stack
For this simply add the DSN hooks
in the handler chain in smtpserver.xml
:
<smtpserver enabled="true"> <...> <!-- The rest of your SMTP configuration, unchanged --> <handlerchain> <handler class="org.apache.james.smtpserver.dsn.DSNEhloHook"/> <handler class="org.apache.james.smtpserver.dsn.DSNMailParameterHook"/> <handler class="org.apache.james.smtpserver.dsn.DSNRcptParameterHook"/> <handler class="org.apache.james.smtpserver.dsn.DSNMessageHook"/> <...> <!-- other handlers, like: --> <handler class="org.apache.james.smtpserver.CoreCmdHandlerLoader"/> <!-- for instance --> </handlerchain> </smtpserver>
Enabling DSN generation as part of mail processing
For the below conditions to be matched we assume you follow RemoteDelivery error handling for MXs, which is a requirement for detailed RemoteDelivery error and delay handling on top of the Distributed server.
Here is a sample mailetcontainer.xml achieving the following DSN generation:
-
Generate a generic
delivered
notification if LocalDelivery succeeded, if requested -
Generate a generic
failed
notification in case of local errors, if requested -
Generate a specific
failed
notification in case of a non existing local user, if requested -
Generate a specific
failed
notification in case of an address rewriting loop, if requested -
Generate a
failed
notification in case of remote permanent errors, if requested. We blame the remote server… -
Generate a
delayed
notification in case of temporary remote errors we are about to retry, if requested. We blame the remote server… -
Generate a
failed
notification in case of temporary remote errors we are not going to retry (failed too many time), if requested. We blame the remote server…
<mailetcontainer enableJmx="true"> <!-- Common processing settings are unchanged --> <processors> <processor state="root" enableJmx="true">\ <!-- Content of root processor is unchanged --> </processor> <processor state="transport" enableJmx="true"> <!-- transport processor unchanged --> </processor> <processor state="error" enableJmx="true"> <mailet match="DSNFailureRequested" class="DSNBounce"> <prefix>[FAILED]</prefix> <passThrough>true</passThrough> <messageString>Hi. This is the James mail server at [machine]. I'm afraid I wasn't able to deliver your message to the following addresses. This is a permanent error; I've given up. Sorry it didn't work out. Below I include the list of recipients, and the reason why I was unable to deliver your message.</messageString> <action>failed</action> <defaultStatus>5.0.0</defaultStatus> </mailet> <mailet match="All" class="ToRepository"> <repositoryPath>cassandra://var/mail/error/</repositoryPath> </mailet> </processor> <processor state="local-delivery" enableJmx="true"> <!-- Your local-delivery pipeline --> <mailet match="All" class="LocalDelivery"> <!-- Do not abort the pipeline yet --> <consume>false</consume> </mailet> <!-- Tell the world we succeeded --> <mailet match="DSNSuccessRequested" class="DSNBounce"> <prefix>[SUCCESS]</prefix> <passThrough>true</passThrough> <messageString>Hi. This is the James mail server at [machine]. I successfully delivered your message to the following addresses. Note that it indicates your recipients received the message but do not imply they read it.</messageString> <action>delivered</action> <defaultStatus>2.0.0</defaultStatus> </mailet> <mailet match="All" class="Null"/> <!-- ignore people not having requesting a dsn success bounce --> </processor> <processor state="relay" enableJmx="true"> <!-- Perform at most 5 RemoteDelivery attempts --> <mailet match="AtMost=5" class="RemoteDelivery"> <outgoingQueue>outgoing</outgoingQueue> <maxRetries>0</maxRetries> <maxDnsProblemRetries>0</maxDnsProblemRetries> <deliveryThreads>10</deliveryThreads> <sendpartial>true</sendpartial> <!-- Use a custom processor for error handling --> <bounceProcessor>remote-delivery-error</bounceProcessor> </mailet> <!-- When retries are exceeded, consider the mail as a permanent failure --> <mailet match="DSNFailureRequested" class="DSNBounce"> <prefix>[FAILED]</prefix> <passThrough>true</passThrough> <messageString>Hi. This is the James mail server at [machine]. I'm afraid I wasn't able to deliver your message to the following addresses. This is a permanent error; I've given up. Sorry it didn't work out. The remote server we should relay this mail to keep on failing. Below I include the list of recipients, and the reason why I was unable to deliver your message.</messageString> <action>failed</action> <defaultStatus>5.0.0</defaultStatus> </mailet> <mailet match="All" class="ToRepository"> <repositoryPath>cassandra://var/mail/error/remote-delivery/permanent/</repositoryPath> </mailet> </processor> <processor state="remote-delivery-error" enableJmx="true"> <matcher name="dsn-permanent" match="org.apache.james.mailetcontainer.impl.matchers.And"> <matcher match="IsRemoteDeliveryPermanentError"/> <matcher match="DSNFailureRequested"/> </matcher> <matcher name="dsn-temporary" match="org.apache.james.mailetcontainer.impl.matchers.And"> <matcher match="IsRemoteDeliveryTemporaryError"/> <matcher match="DSNDelayRequested"/> </matcher> <mailet match="dsn-permanent" class="DSNBounce"> <prefix>[FAILED]</prefix> <passThrough>true</passThrough> <messageString>Hi. This is the James mail server at [machine]. I'm afraid I wasn't able to deliver your message to the following addresses. This is a permanent error; I've given up. Sorry it didn't work out. The remote server we should relay this mail to returns a permanent error. Below I include the list of recipients, and the reason why I was unable to deliver your message.</messageString> <action>failed</action> <defaultStatus>5.0.0</defaultStatus> </mailet> <mailet match="dsn-temporary" class="DSNBounce"> <prefix>[DELAYED]</prefix> <passThrough>true</passThrough> <messageString>Hi. This is the James mail server at [machine]. I'm afraid I wasn't able to deliver your message to the following addresses yet. This is a temporary error: I will keep on trying. Below I include the list of recipients, and the reason why I was unable to deliver your message.</messageString> <action>delayed</action> <defaultStatus>4.0.0</defaultStatus> </mailet> <!-- Error management for remote delivery error handling as described in remote-delivery-error-handling.adoc --> </processor> <processor state="local-address-error" enableJmx="true"> <mailet match="DSNFailureRequested" class="DSNBounce"> <prefix>[FAILED]</prefix> <passThrough>true</passThrough> <messageString>Hi. This is the James mail server at [machine]. I'm afraid I wasn't able to deliver your message to the following addresses. This is a permanent error; I've given up. Sorry it didn't work out. The following addresses do not exist here. Sorry.</messageString> <action>failed</action> <defaultStatus>5.0.0</defaultStatus> </mailet> <mailet match="All" class="ToRepository"> <repositoryPath>cassandra://var/mail/address-error/</repositoryPath> </mailet> </processor> <processor state="relay-denied" enableJmx="true"> <!-- This is an abuse, you likely do not want to be polite with these people. we just keep a copy for later audit & replay --> <mailet match="All" class="ToRepository"> <repositoryPath>cassandra://var/mail/relay-denied/</repositoryPath> <notice>Warning: You are sending an e-mail to a remote server. You must be authenticated to perform such an operation</notice> </mailet> </processor> <processor state="rrt-error" enableJmx="false"> <mailet match="All" class="ToRepository"> <repositoryPath>cassandra://var/mail/rrt-error/</repositoryPath> <passThrough>true</passThrough> </mailet> <mailet match="IsSenderInRRTLoop" class="Null"/> <mailet match="DSNFailureRequested" class="DSNBounce"> <prefix>[FAILED]</prefix> <passThrough>true</passThrough> <messageString>Hi. This is the James mail server at [machine]. I'm afraid I wasn't able to deliver your message to the following addresses. This is a permanent error; I've given up. Sorry it didn't work out. The following addresses is caught in a rewriting loop. An admin should come and fix it (you likely want to report it). Once resolved the admin should be able to resume the processing of your email. Below I include the list of recipients, and the reason why I was unable to deliver your message.</messageString> <action>failed</action> <defaultStatus>5.1.6/defaultStatus> </mailet> </processor> </processors> </mailetcontainer>