-
Notifications
You must be signed in to change notification settings - Fork 473
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JAMES-3823 SMTP Require TLS Option #2460
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hello,
Thanks a LOT for contributions on the topic!
A first remark is that this pull request only tackles incoming SMTP while it necessarily have impact on outgoing SMTP settings: we need to have RemoteDelivery setting up the REQUIRETLS mail parameter if needed... (section 4). I know this will eventually get takkled before we could claim support for REQUIRETLS.
We also need to tackle section 5: preserving those parameters for Bounce
and DSNBounce
mailets.
Hi! I'm still working. In this step, I added the requireStartTls() method for SmtpConfiguration in integration testing and implemented RemoteDelivery. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO we need a way to test this:
GIVEN From REQUIRETLS
WHEN remoteDelivery speaks to a server that do NOT allow startTLS
THEN it fails
Don't we have a way to tweak MockSMTP into allowing testing this.
And yes and VERY good work, by the way.
@@ -123,17 +130,23 @@ public ExecutionResult tryDeliveryToHost(Mail mail, Collection<InternetAddress> | |||
try { | |||
transport = (SMTPTransport) session.getTransport(outgoingMailServer); | |||
transport.setLocalHost(props.getProperty(inContext(session, "mail.smtp.localhost"), configuration.getHeloNameProvider().getHeloName())); | |||
if (isTlsRequired(mail)) { | |||
transport.setStartTLS(true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2 remarks:
- If the transport layer is already configured with SSL there's no point setting SSL. That's the case EG relaying to a secure mail gateway other the internet.
- If the receiver server do not support startTLS this need to throw.
Thanks so much for the review and remarks! Unfortunately, I don't know how to implement it correctly yet. I tried setting the MockSMTP behavior, but that's not what's needed as far as I understand. It is possible to make a tweak to MockSMTP to respond not only to commands, but also to parameters passed. Is it necessary? Further, it is not very clear how and at what point I can check the startTLS allowance for remoteDelivery. Also a question regarding Bounce and DSNBounce maillets. The REQUIRETLS email attribute will be saved as it is, what do I need to add additionally? I apologize for the large scope of questions. |
void remoteDeliveryShouldFailsWhenServerNotAllowStartTls(DockerMockSmtp mockSmtp) throws Exception { | ||
testIMAPClient.connect(LOCALHOST_IP, jamesServer.getProbe(ImapGuiceProbe.class).getImapPort()) | ||
.login(FROM, PASSWORD); | ||
|
||
MockSMTPBehavior startTlsBehavior = new MockSMTPBehavior( | ||
MAIL_FROM, | ||
Condition.MATCH_ALL, | ||
new Response(COMMAND_PARAMETER_NOT_IMPLEMENTED_504, "The server has not implemented a command parameter"), | ||
MockSMTPBehavior.NumberOfAnswersPolicy.anytime()); | ||
|
||
mockSmtp.getConfigurationClient().setBehaviors(List.of(startTlsBehavior)); | ||
|
||
SMTPSClient smtpClient = initSMTPSClient(); | ||
smtpClient.mail("<" + FROM + "> REQUIRETLS"); | ||
smtpClient.rcpt("<" + RECIPIENT + ">"); | ||
smtpClient.sendShortMessageData("A short message..."); | ||
|
||
String dsnMessage = testIMAPClient.connect(LOCALHOST_IP, jamesServer.getProbe(ImapGuiceProbe.class).getImapPort()) | ||
.login(FROM, PASSWORD) | ||
.select(TestIMAPClient.INBOX) | ||
.awaitMessageCount(awaitAtMostOneMinute, 1) | ||
.readFirstMessage(); | ||
|
||
Assertions.assertThat(dsnMessage).contains("504 The server has not implemented a command parameter"); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No what we want is the mock server to HIDE that it implements STARTTLS (in the EHLO capability).
When that's the case the relay of the mail should fail.
This is different from failing at MAIL FROM
(What I mean is that the test is inaccurate).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No what we want is the mock server to HIDE that it implements STARTTLS (in the EHLO capability).
When that's the case the relay of the mail should fail.
This is different from failing at MAIL FROM
(What I mean is that the test is inaccurate).
I agree with you, and I propose a new version of the test
@@ -131,6 +133,9 @@ public ExecutionResult tryDeliveryToHost(Mail mail, Collection<InternetAddress> | |||
transport = (SMTPTransport) session.getTransport(outgoingMailServer); | |||
transport.setLocalHost(props.getProperty(inContext(session, "mail.smtp.localhost"), configuration.getHeloNameProvider().getHeloName())); | |||
connect(outgoingMailServer, transport); | |||
if (!transport.getLastServerResponse().contains("STARTTLS")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should do this only if TLS is required
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wasn;t reviwing latest diff, sorry
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
public class SmtpTlsMessageHook implements JamesMessageHook { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public class SmtpTlsMessageHook implements JamesMessageHook { | |
public class SmtpRequireTlsMessageHook implements JamesMessageHook { |
import org.apache.james.protocols.smtp.hook.HeloHook; | ||
import org.apache.james.protocols.smtp.hook.HookResult; | ||
|
||
public class SmtpTlsEhloHook implements HeloHook { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public class SmtpTlsEhloHook implements HeloHook { | |
public class SmtpRequireTlsEhloHook implements HeloHook { |
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
public class SmtpTlsParameterHook implements MailParametersHook { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public class SmtpTlsParameterHook implements MailParametersHook { | |
public class SmtpRequireTlsParameterHook implements MailParametersHook { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very good work.
I endorse this, and just find comments onto the naming of the hooks.
Thank you! If there are any additional suggestions for improving this contribution, I am willing to follow up. It would be interesting if this could be tested on a test bench somehow. Thanks again for the code review and feedback on the work |
I assume firstly that in order for CI to work properly when running tests with MAIL FROM parameters with no value, we need to update the version of the mock smtp server in the docker hub. See: |
Will do tomorrow! (sorry) |
I did also re-trigger a build. |
Thanks for updating the mock smtp server. I see that some of the related tests failed, sorry, I will need more time to find the reason. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error looks unrelated on the CI so I restarted the build!
JAMES-3823
Hi! The first step in the direction of SMTP Require TLS Option is a basic set of hooks. In the future I plan to enhance this PR by processing of new REQUIRETLS attribute, handling headers, remote delivery, etc.