Skip to content

Commit 6373fe2

Browse files
authored
Bugs(smtp): AUTH extension does not allow AUTH param on MAIL FROM. Resolves #565 (#1728)
1 parent 659e1af commit 6373fe2

File tree

2 files changed

+73
-0
lines changed

2 files changed

+73
-0
lines changed

smtpserver/Rnwood.SmtpServer.Tests/Extensions/Auth/AuthExtensionProcessorTests.cs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ public class AuthExtensionProcessorTests
1313
public async Task GetEHLOKeywords_ReturnsIdentifiers()
1414
{
1515
TestMocks mocks = new TestMocks();
16+
mocks.Connection.Setup(c => c.MailVerb).Returns(new MailVerb());
1617
mocks.ServerOptions.Setup(sb => sb.IsAuthMechanismEnabled(
1718
It.IsAny<IConnection>(),
1819
It.IsAny<IAuthMechanism>()
@@ -33,4 +34,61 @@ public async Task GetEHLOKeywords_ReturnsIdentifiers()
3334
Assert.Contains(ids, id => id == "PLAIN");
3435
}
3536
}
37+
38+
[Fact]
39+
public async Task MailFrom_AllowsAuthParameterWithValue()
40+
{
41+
TestMocks mocks = new TestMocks();
42+
mocks.Connection.Setup(c => c.MailVerb).Returns(new MailVerb());
43+
mocks.Connection.Setup(c => c.NewMessage()).ReturnsAsync(() => {
44+
var message = new MemoryMessageBuilder();
45+
mocks.Connection.Setup(c => c.CurrentMessage).Returns(message);
46+
return message;
47+
});
48+
49+
50+
AuthExtensionProcessor authExtensionProcessor = new AuthExtensionProcessor(mocks.Connection.Object);
51+
await mocks.Connection.Object.MailVerb.FromSubVerb.Process(mocks.Connection.Object, new SmtpCommand("MAIL FROM:<[email protected]> [email protected]"));
52+
53+
mocks.VerifyWriteResponse(StandardSmtpResponseCode.OK);
54+
}
55+
56+
[Fact]
57+
public async Task MailFrom_AllowsAuthParameterWithEmptyPlaceholderValue()
58+
{
59+
TestMocks mocks = new TestMocks();
60+
mocks.Connection.Setup(c => c.MailVerb).Returns(new MailVerb());
61+
mocks.Connection.Setup(c => c.NewMessage()).ReturnsAsync(() => {
62+
var message = new MemoryMessageBuilder();
63+
mocks.Connection.Setup(c => c.CurrentMessage).Returns(message);
64+
return message;
65+
});
66+
67+
68+
AuthExtensionProcessor authExtensionProcessor = new AuthExtensionProcessor(mocks.Connection.Object);
69+
await mocks.Connection.Object.MailVerb.FromSubVerb.Process(mocks.Connection.Object, new SmtpCommand("MAIL FROM:<[email protected]> AUTH=<>"));
70+
71+
mocks.VerifyWriteResponse(StandardSmtpResponseCode.OK);
72+
}
73+
74+
[Fact]
75+
public async Task MailFrom_DoesNotAllowAuthParameterWithEmptyValue()
76+
{
77+
TestMocks mocks = new TestMocks();
78+
mocks.Connection.Setup(c => c.MailVerb).Returns(new MailVerb());
79+
mocks.Connection.Setup(c => c.NewMessage()).ReturnsAsync(() => {
80+
var message = new MemoryMessageBuilder();
81+
mocks.Connection.Setup(c => c.CurrentMessage).Returns(message);
82+
return message;
83+
});
84+
85+
86+
AuthExtensionProcessor authExtensionProcessor = new AuthExtensionProcessor(mocks.Connection.Object);
87+
88+
var exception = await Assert.ThrowsAsync<SmtpServerException>(async () =>
89+
{
90+
await mocks.Connection.Object.MailVerb.FromSubVerb.Process(mocks.Connection.Object, new SmtpCommand("MAIL FROM:<[email protected]> AUTH="));
91+
});
92+
Assert.Equal((int) StandardSmtpResponseCode.SyntaxErrorInCommandArguments, exception.SmtpResponse.Code);
93+
}
3694
}

smtpserver/Rnwood.SmtpServer/Extensions/Auth/AuthExtensionProcessor.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ public AuthExtensionProcessor(IConnection connection)
3535
}
3636

3737
connection.VerbMap.SetVerbProcessor("AUTH", new AuthVerb(this));
38+
39+
connection.MailVerb.FromSubVerb.ParameterProcessorMap.SetProcessor("AUTH", new AuthMailFromParameterProcessor());
3840
}
3941

4042
/// <summary>
@@ -86,4 +88,17 @@ protected async Task<IEnumerable<IAuthMechanism>> GetEnabledAuthMechanisms()
8688

8789
return result;
8890
}
91+
92+
private class AuthMailFromParameterProcessor : IParameterProcessor
93+
{
94+
public Task SetParameter(IConnection connection, string key, string value)
95+
{
96+
if (string.IsNullOrEmpty(value))
97+
{
98+
throw new SmtpServerException(new SmtpResponse(StandardSmtpResponseCode.SyntaxErrorInCommandArguments, "AUTH parameter must have a value or <>"));
99+
}
100+
101+
return Task.CompletedTask;
102+
}
103+
}
89104
}

0 commit comments

Comments
 (0)