Skip to content

Commit 2b455e6

Browse files
committed
fixed bug with not handling multiple buffers in the token reader properly
1 parent f0b6751 commit 2b455e6

13 files changed

+227
-90
lines changed

Examples/SampleApp/Examples/SessionTracingExample.cs

+13-1
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,11 @@ public static void Run()
2121
.Build();
2222

2323
var server = new SmtpServer.SmtpServer(options, ServiceProvider.Default);
24-
24+
2525
server.SessionCreated += OnSessionCreated;
2626
server.SessionCompleted += OnSessionCompleted;
27+
server.SessionFaulted += OnSessionFaulted;
28+
server.SessionCancelled += OnSessionCancelled;
2729

2830
var serverTask = server.StartAsync(_cancellationTokenSource.Token);
2931

@@ -32,6 +34,16 @@ public static void Run()
3234
serverTask.WaitWithoutException();
3335
}
3436

37+
static void OnSessionFaulted(object sender, SessionFaultedEventArgs e)
38+
{
39+
Console.WriteLine("SessionFaulted: {0}", e.Exception);
40+
}
41+
42+
static void OnSessionCancelled(object sender, SessionEventArgs e)
43+
{
44+
Console.WriteLine("SessionCancelled");
45+
}
46+
3547
static void OnSessionCreated(object sender, SessionEventArgs e)
3648
{
3749
Console.WriteLine("SessionCreated: {0}", e.Context.Properties[EndpointListener.RemoteEndPointKey]);

Examples/SampleApp/Program.cs

+7-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
using MimeKit;
99
using SampleApp.Examples;
1010
using SmtpServer.IO;
11+
using SmtpServer.Protocol;
12+
using SmtpServer.Tests;
1113
using SmtpServer.Text;
1214

1315
namespace SampleApp
@@ -22,9 +24,12 @@ static void Main(string[] args)
2224
//SimpleServerExample.Run();
2325
//CustomEndpointListenerExample.Run();
2426
//ServerCancellingExample.Run();
25-
//SessionTracingExample.Run();
27+
SessionTracingExample.Run();
2628
//DependencyInjectionExample.Run();
27-
SecureServerExample.Run();
29+
//SecureServerExample.Run();
30+
31+
//SampleMailClient.Send(user: "user1", password: "password1", useSsl: false, port: 587);
32+
//SampleMailClient.Send(useSsl: false, port: 587);
2833

2934
//var files = Directory.GetFiles(@"C:\Temp\enron_mail_20150507.tar", "*.*", SearchOption.AllDirectories).ToList();
3035
//Console.WriteLine(files.OrderByDescending(file => new FileInfo(file).Length).First());

Examples/SampleApp/SampleApp.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
</ItemGroup>
2020

2121
<ItemGroup>
22+
<ProjectReference Include="..\..\Src\SmtpServer.Tests\SmtpServer.Tests.csproj" />
2223
<ProjectReference Include="..\..\Src\SmtpServer\SmtpServer.csproj" />
2324
</ItemGroup>
2425

Examples/SampleApp/SampleMailClient.cs

+7-2
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,18 @@ public static void Send(
1313
string password = null,
1414
MimeEntity body = null,
1515
int count = 1,
16-
bool useSsl = false)
16+
bool useSsl = false,
17+
int port = 9025)
1718
{
1819
//var message = MimeMessage.Load(@"C:\Dev\Cain\Temp\message.eml");
1920
var message = new MimeMessage();
2021

2122
message.From.Add(MailboxAddress.Parse(from ?? "[email protected]"));
2223
message.To.Add(MailboxAddress.Parse(to ?? "[email protected]"));
24+
//for (var i = 0; i < 400; i++)
25+
//{
26+
// message.To.Add(MailboxAddress.Parse(to ?? $"testuser{i+1000}@longemaildomain1000001.com"));
27+
//}
2328
message.Subject = subject ?? "Hello";
2429
message.Body = body ?? new TextPart("plain")
2530
{
@@ -28,7 +33,7 @@ public static void Send(
2833

2934
using var client = new SmtpClient();
3035

31-
client.Connect("localhost", 9025, useSsl);
36+
client.Connect("localhost", port, useSsl);
3237

3338
if (user != null && password != null)
3439
{

Src/SmtpServer.Tests/SmtpParserTests.cs

+33
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Collections.Generic;
44
using System.Net;
55
using System.Text;
6+
using SmtpServer.IO;
67
using SmtpServer.Mail;
78
using SmtpServer.Protocol;
89
using SmtpServer.Text;
@@ -19,6 +20,18 @@ static TokenReader CreateReader(string text)
1920
return new TokenReader(new ReadOnlySequence<byte>(buffer, 0, buffer.Length));
2021
}
2122

23+
static TokenReader CreateReader(params byte[][] buffers)
24+
{
25+
var segmentList = new ByteArraySegmentList();
26+
27+
foreach (var buffer in buffers)
28+
{
29+
segmentList.Append(buffer);
30+
}
31+
32+
return new TokenReader(segmentList.Build());
33+
}
34+
2235
static SmtpParser Parser => new SmtpParser(new SmtpCommandFactory());
2336

2437
[Fact]
@@ -210,6 +223,9 @@ public void CanNotMakeMail(string input)
210223
[InlineData("RCPT TO:<[email protected]>", "cain.osullivan", "gmail.com")]
211224
[InlineData(@"RCPT TO:<""Abc@def""@example.com>", "Abc@def", "example.com")]
212225
[InlineData("RCPT TO:<pelé@example.com>", "pelé", "example.com")]
226+
[InlineData("RCPT TO:<@example1.com:[email protected]>", "someone", "example.com")]
227+
[InlineData("RCPT TO:<@example1.com,@example2.com:[email protected]>", "someone", "example.com")]
228+
[InlineData("RCPT TO:<example/[email protected]>", "example/example", "example.com")]
213229
public void CanMakeRcpt(string input, string user, string host)
214230
{
215231
// arrange
@@ -225,6 +241,22 @@ public void CanMakeRcpt(string input, string user, string host)
225241
Assert.Equal(host, ((RcptCommand)command).Address.Host);
226242
}
227243

244+
[Theory]
245+
[InlineData("RCPT TO:<someone@@example.com>")]
246+
[InlineData("RCPT TO:<[email protected]>")]
247+
[InlineData("RCPT TO:<someone@-examplecom>")]
248+
public void CanNotMakeRcpt(string input)
249+
{
250+
// arrange
251+
var reader = CreateReader(input);
252+
253+
// act
254+
var result = Parser.TryMakeRcpt(ref reader, out _, out _);
255+
256+
// assert
257+
Assert.False(result);
258+
}
259+
228260
[Fact]
229261
public void CanMakeProxyUnknown()
230262
{
@@ -389,6 +421,7 @@ public void CanMakeDomain()
389421
[InlineData(@"[email protected]", "$A12345", "example.com")]
390422
[InlineData(@"!def!xyz%[email protected]", "!def!xyz%abc", "example.com")]
391423
[InlineData(@"[email protected]", "_somename", "example.com")]
424+
[InlineData(@"[email protected]", "somename", "127.0.0.1")]
392425
public void CanMakeMailbox(string email, string user, string host)
393426
{
394427
// arrange

Src/SmtpServer.Tests/TokenReaderTests.cs

+42
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,47 @@ public void CanTokenizeMultiSegmentWord()
4444
Assert.Equal("DEF", reader.Take().ToText());
4545
Assert.Equal(TokenKind.None, reader.Take().Kind);
4646
}
47+
48+
[Fact]
49+
public void CanMakeSequences()
50+
{
51+
// arrange
52+
var reader = CreateReader("1", "AB", "CDE", "F234", "5678");
53+
54+
// act
55+
var made1 = reader.TryMake(TryMakeNumber, out var sequence1);
56+
var made2 = reader.TryMake(TryMakeText, out var sequence2);
57+
var made3 = reader.TryMake(TryMakeNumber, out var sequence3);
58+
59+
// assert
60+
Assert.True(made1);
61+
Assert.Equal("1", StringUtil.Create(sequence1));
62+
Assert.True(made2);
63+
Assert.Equal("ABCDEF", StringUtil.Create(sequence2));
64+
Assert.True(made3);
65+
Assert.Equal("2345678", StringUtil.Create(sequence3));
66+
67+
static bool TryMakeText(ref TokenReader r)
68+
{
69+
if (r.Peek().Kind == TokenKind.Text)
70+
{
71+
r.Skip(TokenKind.Text);
72+
return true;
73+
}
74+
75+
return false;
76+
}
77+
78+
static bool TryMakeNumber(ref TokenReader r)
79+
{
80+
if (r.Peek().Kind == TokenKind.Number)
81+
{
82+
r.Skip(TokenKind.Number);
83+
return true;
84+
}
85+
86+
return false;
87+
}
88+
}
4789
}
4890
}

Src/SmtpServer/IO/BuffersExtension.cs

+60
Original file line numberDiff line numberDiff line change
@@ -130,5 +130,65 @@ static bool TryMoveNext(ref ReadOnlySequence<byte> source, ref SequencePosition
130130
span = default;
131131
return false;
132132
}
133+
134+
internal static bool CaseInsensitiveStringEquals(this ReadOnlySequence<byte> buffer, ref Span<char> text)
135+
{
136+
if (buffer.IsSingleSegment)
137+
{
138+
var span = buffer.First.Span;
139+
140+
return CaseInsensitiveStringEquals(ref span, ref text, 0);
141+
}
142+
143+
var i = 0;
144+
var position = buffer.GetPosition(0);
145+
146+
while (buffer.TryGet(ref position, out var memory, advance: true))
147+
{
148+
var span = memory.Span;
149+
150+
if (CaseInsensitiveStringEquals(ref span, ref text, i) == false)
151+
{
152+
return false;
153+
}
154+
155+
i += span.Length;
156+
}
157+
158+
return i > 0;
159+
}
160+
161+
static bool CaseInsensitiveStringEquals(ref ReadOnlySpan<byte> span, ref Span<char> text, int offset)
162+
{
163+
if (text.Length - offset != span.Length)
164+
{
165+
return false;
166+
}
167+
168+
for (var i = 0; i < span.Length; i++)
169+
{
170+
var ch = (char)span[i];
171+
172+
if (char.ToUpper(ch) != char.ToUpper(text[i + offset]))
173+
{
174+
return false;
175+
}
176+
}
177+
178+
return true;
179+
}
180+
181+
internal static bool IsHex(this ref ReadOnlySpan<byte> buffer)
182+
{
183+
for (var i = 0; i < buffer.Length; i++)
184+
{
185+
if ((buffer[i] < 'a' || buffer[i] > 'f') && (buffer[i] < 'A' || buffer[i] > 'F'))
186+
{
187+
return false;
188+
}
189+
}
190+
191+
return true;
192+
}
133193
}
134194
}

Src/SmtpServer/Protocol/SmtpParser.cs

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Net;
55
using System.Text;
66
using System.Text.RegularExpressions;
7+
using SmtpServer.IO;
78
using SmtpServer.Mail;
89
using SmtpServer.Text;
910

Src/SmtpServer/SmtpServer.cs

+4-1
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,10 @@ async Task ListenAsync(IEndpointDefinition endpointDefinition, CancellationToken
141141
continue;
142142
}
143143

144-
_sessions.Run(sessionContext, cancellationTokenSource.Token);
144+
if (sessionContext.Pipe != null)
145+
{
146+
_sessions.Run(sessionContext, cancellationTokenSource.Token);
147+
}
145148
}
146149
}
147150

Src/SmtpServer/SmtpServer.csproj

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<LangVersion>8.0</LangVersion>
66
<AssemblyName>SmtpServer</AssemblyName>
77
<RootNamespace>SmtpServer</RootNamespace>
8-
<Version>9.0.0</Version>
8+
<Version>9.0.1</Version>
99
<Description>.NET SmtpServer</Description>
1010
<Authors>Cain O'Sullivan</Authors>
1111
<Company />
@@ -15,8 +15,8 @@
1515
<PackageTags>smtp smtpserver smtp server</PackageTags>
1616
<PackageLicenseUrl></PackageLicenseUrl>
1717
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
18-
<AssemblyVersion>9.0.0.0</AssemblyVersion>
19-
<FileVersion>9.0.0.0</FileVersion>
18+
<AssemblyVersion>9.0.1.0</AssemblyVersion>
19+
<FileVersion>9.0.1.0</FileVersion>
2020
<PackageReleaseNotes>Version 9
2121
Breaking API change by removing the Certificate from the server options and adding it to the endpoint.
2222

Src/SmtpServer/SmtpSessionManager.cs

+2
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ async Task RunAsync(SmtpSessionHandle handle, CancellationToken cancellationToke
3636
{
3737
try
3838
{
39+
cancellationToken.ThrowIfCancellationRequested();
40+
3941
_smtpServer.OnSessionCreated(new SessionEventArgs(handle.SessionContext));
4042

4143
await handle.Session.RunAsync(cancellationToken);

Src/SmtpServer/Text/BufferExtensions.cs

-48
This file was deleted.

0 commit comments

Comments
 (0)