cosullivan / SmtpServer

A SMTP Server component written in C#
MIT License
675 stars 159 forks source link

Mail is received, but the SessionCompleted event is not triggered / SessionFaulted #205

Closed tinohager closed 8 months ago

tinohager commented 1 year ago

I can receive mails perfectly with my test mail server. The mails are stored and everything works fine. But I noticed that the SessionCompleted event is not fired. Now I have also added SessionFaulted to the log output and here I get an exception. For unsecured connections as well as secured connections.

The problem seems to occur only under Linux. I was not able to reproduce it on my Windows computer.

Secure

info: DockerMailReceiver.SmtpServerWorker[0]
      SessionCreated - Port:25 IsSecure:False RemoteEndpoint:40.92.75.65
info: DockerMailReceiver.MailboxFilterFactories.DefaultMailboxFilterFactory[0]
      DefaultMailboxFilterFactory - Port:25 IsSecure:True RemoteEndpoint:40.92.75.65
info: DockerMailReceiver.MailboxFilterFactories.DefaultMailboxFilterFactory[0]
      DefaultMailboxFilterFactory - Port:25 IsSecure:True RemoteEndpoint:40.92.75.65
info: DockerMailReceiver.SmtpServerWorker[0]
      SessionFaulted - System.IO.IOException: Unable to write data to the transport connection: Connection reset by peer.
       ---> System.Net.Sockets.SocketException (104): Connection reset by peer
         at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.CreateException(SocketError , Boolean )
         at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.SendAsyncForNetworkStream(Socket , CancellationToken )
         at System.Net.Sockets.Socket.SendAsyncForNetworkStream(ReadOnlyMemory`1 , SocketFlags , CancellationToken )
         at System.Net.Sockets.NetworkStream.WriteAsync(ReadOnlyMemory`1 , CancellationToken )
         at System.Net.Security.SslStream.WriteSingleChunk[TIOAdapter](TIOAdapter , ReadOnlyMemory`1 )
         at System.Net.Security.SslStream.WriteAsyncInternal[TIOAdapter](TIOAdapter , ReadOnlyMemory`1 )
         at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& )
         at System.Net.Security.SslStream.WriteAsyncInternal[TIOAdapter](TIOAdapter , ReadOnlyMemory`1 )
         at System.Net.Security.SslStream.WriteAsync(ReadOnlyMemory`1 , CancellationToken )
         at System.IO.Pipelines.StreamPipeWriter.FlushAsyncInternal(Boolean , ReadOnlyMemory`1 , CancellationToken )
         at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& )
         at System.IO.Pipelines.StreamPipeWriter.FlushAsyncInternal(Boolean , ReadOnlyMemory`1 , CancellationToken )
         at System.IO.Pipelines.StreamPipeWriter.FlushAsync(CancellationToken )
         at SmtpServer.IO.PipeWriterExtensions.WriteReplyAsync(PipeWriter writer, SmtpResponse response, CancellationToken cancellationToken)
         at SmtpServer.Protocol.QuitCommand.ExecuteAsync(SmtpSessionContext context, CancellationToken cancellationToken)
         at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& )
         at SmtpServer.Protocol.QuitCommand.ExecuteAsync(SmtpSessionContext context, CancellationToken cancellationToken)
         at SmtpServer.SmtpSession.ExecuteAsync(SmtpCommand command, SmtpSessionContext context, CancellationToken cancellationToken)
         at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& )
         at SmtpServer.SmtpSession.ExecuteAsync(SmtpCommand command, SmtpSessionContext context, CancellationToken cancellationToken)
         at SmtpServer.SmtpSession.ExecuteAsync(SmtpSessionContext context, CancellationToken cancellationToken)
         at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.ExecutionContextCallback(Object )
         at System.Threading.ExecutionContext.RunInternal(ExecutionContext , ContextCallback , Object )
         at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext(Thread )
         at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext()
         at System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(IAsyncStateMachineBox , Boolean )
         at System.Threading.Tasks.Task.RunContinuations(Object )
         at System.Threading.Tasks.Task`1.TrySetResult(TResult )
         at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.SetExistingTaskResult(Task`1 , TResult )
         at System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder`1.SetResult(TResult )
         at SmtpServer.SmtpSession.ReadCommandAsync(ISessionContext context, CancellationToken cancellationToken)
         at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.ExecutionContextCallback(Object )
         at System.Threading.ExecutionContext.RunInternal(ExecutionContext , ContextCallback , Object )
         at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext(Thread )
         at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext()
         at System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(IAsyncStateMachineBox , Boolean )
         at System.Threading.Tasks.Task.RunContinuations(Object )
         at System.Threading.Tasks.Task`1.TrySetResult(TResult )
         at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.SetExistingTaskResult(Task`1 , TResult )
         at System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder.SetResult()
         at SmtpServer.IO.PipeReaderExtensions.ReadUntilAsync(PipeReader reader, Byte[] sequence, Func`2 func, CancellationToken cancellationToken)
         at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.ExecutionContextCallback(Object )
         at System.Threading.ExecutionContext.RunInternal(ExecutionContext , ContextCallback , Object )
         at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext(Thread )
         at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext()
         at System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(IAsyncStateMachineBox , Boolean )
         at System.Threading.Tasks.Task.RunContinuations(Object )
         at System.Threading.Tasks.Task`1.TrySetResult(TResult )
         at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.SetExistingTaskResult(Task`1 , TResult )
         at System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder`1.SetResult(TResult )
         at System.IO.Pipelines.StreamPipeReader.<ReadAsync>g__Core|36_0(StreamPipeReader , CancellationTokenSource , CancellationToken )
         at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.ExecutionContextCallback(Object )
         at System.Threading.ExecutionContext.RunInternal(ExecutionContext , ContextCallback , Object )
         at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext(Thread )
         at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext()
         at System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(IAsyncStateMachineBox , Boolean )
         at System.Threading.Tasks.Task.RunContinuations(Object )
         at System.Threading.Tasks.Task`1.TrySetResult(TResult )
         at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.SetExistingTaskResult(Task`1 , TResult )
         at System.Net.Security.SslStream.ReadAsyncInternal[TIOAdapter](TIOAdapter , Memory`1 )
         at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.ExecutionContextCallback(Object )
         at System.Threading.ExecutionContext.RunInternal(ExecutionContext , ContextCallback , Object )
         at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext(Thread )
         at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext()
         at System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(IAsyncStateMachineBox , Boolean )
         at System.Threading.Tasks.Task.RunContinuations(Object )
         at System.Threading.Tasks.Task`1.TrySetResult(TResult )
         at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.SetExistingTaskResult(Task`1 , TResult )
         at System.Net.Security.SslStream.EnsureFullTlsFrameAsync[TIOAdapter](TIOAdapter )
         at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.ExecutionContextCallback(Object )
         at System.Threading.ExecutionContext.RunInternal(ExecutionContext , ContextCallback , Object )
         at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext(Thread )
         at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext()
         at System.Threading.ThreadPool.<>c.<.cctor>b__86_0(Object )
         at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.InvokeContinuation(Action`1 , Object , Boolean , Boolean )
         at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.OnCompleted(SocketAsyncEventArgs )
         at System.Net.Sockets.SocketAsyncEventArgs.OnCompletedInternal()
         at System.Net.Sockets.SocketAsyncEventArgs.FinishOperationAsyncSuccess(Int32 , SocketFlags )
         at System.Net.Sockets.SocketAsyncEventArgs.CompletionCallback(Int32 , SocketFlags , SocketError )
         at System.Net.Sockets.SocketAsyncEventArgs.TransferCompletionCallbackCore(Int32 , Byte[] , Int32 , SocketFlags , SocketError )
         at System.Net.Sockets.SocketAsyncContext.BufferMemoryReceiveOperation.InvokeCallback(Boolean )
         at System.Net.Sockets.SocketAsyncContext.OperationQueue`1.ProcessAsyncOperation(TOperation )
         at System.Net.Sockets.SocketAsyncContext.ProcessAsyncReadOperation(ReadOperation )
         at System.Net.Sockets.SocketAsyncContext.ReadOperation.System.Threading.IThreadPoolWorkItem.Execute()
         at System.Net.Sockets.SocketAsyncContext.AsyncOperation.Process()
         at System.Net.Sockets.SocketAsyncContext.HandleEvents(SocketEvents )
         at System.Net.Sockets.SocketAsyncEngine.System.Threading.IThreadPoolWorkItem.Execute()
         at System.Threading.ThreadPoolWorkQueue.Dispatch()
         at System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart()
         at System.Threading.Thread.StartCallback()
      --- End of stack trace from previous location ---

         --- End of inner exception stack trace ---
         at System.Net.Security.SslStream.<WriteSingleChunk>g__CompleteWriteAsync|182_1[TIOAdapter](ValueTask , Byte[] )
         at System.Net.Security.SslStream.WriteAsyncInternal[TIOAdapter](TIOAdapter , ReadOnlyMemory`1 )
         at System.IO.Pipelines.StreamPipeWriter.FlushAsyncInternal(Boolean , ReadOnlyMemory`1 , CancellationToken )
         at SmtpServer.Protocol.QuitCommand.ExecuteAsync(SmtpSessionContext context, CancellationToken cancellationToken)
         at SmtpServer.SmtpSession.ExecuteAsync(SmtpCommand command, SmtpSessionContext context, CancellationToken cancellationToken)
         at SmtpServer.SmtpSession.ExecuteAsync(SmtpSessionContext context, CancellationToken cancellationToken)
         at SmtpServer.SmtpSession.RunAsync(CancellationToken cancellationToken)
         at SmtpServer.SmtpSessionManager.RunAsync(SmtpSessionHandle handle, CancellationToken cancellationToken)

Unsecure

info: DockerMailReceiver.SmtpServerWorker[0]
      SessionCreated - Port:25 IsSecure:False RemoteEndpoint:40.92.74.56
info: DockerMailReceiver.MailboxFilterFactories.DefaultMailboxFilterFactory[0]
      DefaultMailboxFilterFactory - Port:25 IsSecure:False RemoteEndpoint:40.92.74.56
info: DockerMailReceiver.MailboxFilterFactories.DefaultMailboxFilterFactory[0]
      DefaultMailboxFilterFactory - Port:25 IsSecure:False RemoteEndpoint:40.92.74.56
info: DockerMailReceiver.SmtpServerWorker[0]
      SessionFaulted - System.IO.IOException: Unable to write data to the transport connection: Connection reset by peer.
       ---> System.Net.Sockets.SocketException (104): Connection reset by peer
         at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.CreateException(SocketError , Boolean )
         at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.SendAsyncForNetworkStream(Socket , CancellationToken )
         at System.Net.Sockets.Socket.SendAsyncForNetworkStream(ReadOnlyMemory`1 , SocketFlags , CancellationToken )
         at System.Net.Sockets.NetworkStream.WriteAsync(ReadOnlyMemory`1 , CancellationToken )
         at System.IO.Pipelines.StreamPipeWriter.FlushAsyncInternal(Boolean , ReadOnlyMemory`1 , CancellationToken )
         at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& )
         at System.IO.Pipelines.StreamPipeWriter.FlushAsyncInternal(Boolean , ReadOnlyMemory`1 , CancellationToken )
         at System.IO.Pipelines.StreamPipeWriter.FlushAsync(CancellationToken )
         at SmtpServer.IO.PipeWriterExtensions.WriteReplyAsync(PipeWriter writer, SmtpResponse response, CancellationToken cancellationToken)
         at SmtpServer.Protocol.QuitCommand.ExecuteAsync(SmtpSessionContext context, CancellationToken cancellationToken)
         at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& )
         at SmtpServer.Protocol.QuitCommand.ExecuteAsync(SmtpSessionContext context, CancellationToken cancellationToken)
         at SmtpServer.SmtpSession.ExecuteAsync(SmtpCommand command, SmtpSessionContext context, CancellationToken cancellationToken)
         at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& )
         at SmtpServer.SmtpSession.ExecuteAsync(SmtpCommand command, SmtpSessionContext context, CancellationToken cancellationToken)
         at SmtpServer.SmtpSession.ExecuteAsync(SmtpSessionContext context, CancellationToken cancellationToken)
         at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.ExecutionContextCallback(Object )
         at System.Threading.ExecutionContext.RunInternal(ExecutionContext , ContextCallback , Object )
         at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext(Thread )
         at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext()
         at System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(IAsyncStateMachineBox , Boolean )
         at System.Threading.Tasks.Task.RunContinuations(Object )
         at System.Threading.Tasks.Task.FinishContinuations()
         at System.Threading.Tasks.Task`1.TrySetResult(TResult )
         at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.SetExistingTaskResult(Task`1 , TResult )
         at System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder`1.SetResult(TResult )
         at SmtpServer.SmtpSession.ReadCommandAsync(ISessionContext context, CancellationToken cancellationToken)
         at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.ExecutionContextCallback(Object )
         at System.Threading.ExecutionContext.RunInternal(ExecutionContext , ContextCallback , Object )
         at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext(Thread )
         at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext()
         at System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(IAsyncStateMachineBox , Boolean )
         at System.Threading.Tasks.Task.RunContinuations(Object )
         at System.Threading.Tasks.Task.FinishContinuations()
         at System.Threading.Tasks.Task`1.TrySetResult(TResult )
         at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.SetExistingTaskResult(Task`1 , TResult )
         at System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder.SetResult()
         at SmtpServer.IO.PipeReaderExtensions.ReadUntilAsync(PipeReader reader, Byte[] sequence, Func`2 func, CancellationToken cancellationToken)
         at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.ExecutionContextCallback(Object )
         at System.Threading.ExecutionContext.RunInternal(ExecutionContext , ContextCallback , Object )
         at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext(Thread )
         at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext()
         at System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(IAsyncStateMachineBox , Boolean )
         at System.Threading.Tasks.Task.RunContinuations(Object )
         at System.Threading.Tasks.Task.FinishContinuations()
         at System.Threading.Tasks.Task`1.TrySetResult(TResult )
         at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.SetExistingTaskResult(Task`1 , TResult )
         at System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder`1.SetResult(TResult )
         at System.IO.Pipelines.StreamPipeReader.<ReadAsync>g__Core|36_0(StreamPipeReader , CancellationTokenSource , CancellationToken )
         at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.ExecutionContextCallback(Object )
         at System.Threading.ExecutionContext.RunInternal(ExecutionContext , ContextCallback , Object )
         at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext(Thread )
         at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext()
         at System.Threading.ThreadPool.<>c.<.cctor>b__86_0(Object )
         at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.InvokeContinuation(Action`1 , Object , Boolean , Boolean )
         at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.OnCompleted(SocketAsyncEventArgs )
         at System.Net.Sockets.SocketAsyncEventArgs.OnCompletedInternal()
         at System.Net.Sockets.SocketAsyncEventArgs.FinishOperationAsyncSuccess(Int32 , SocketFlags )
         at System.Net.Sockets.SocketAsyncEventArgs.CompletionCallback(Int32 , SocketFlags , SocketError )
         at System.Net.Sockets.SocketAsyncEventArgs.TransferCompletionCallbackCore(Int32 , Byte[] , Int32 , SocketFlags , SocketError )
         at System.Net.Sockets.SocketAsyncContext.BufferMemoryReceiveOperation.InvokeCallback(Boolean )
         at System.Net.Sockets.SocketAsyncContext.OperationQueue`1.ProcessAsyncOperation(TOperation )
         at System.Net.Sockets.SocketAsyncContext.ProcessAsyncReadOperation(ReadOperation )
         at System.Net.Sockets.SocketAsyncContext.ReadOperation.System.Threading.IThreadPoolWorkItem.Execute()
         at System.Net.Sockets.SocketAsyncContext.AsyncOperation.Process()
         at System.Net.Sockets.SocketAsyncContext.HandleEvents(SocketEvents )
         at System.Net.Sockets.SocketAsyncEngine.System.Threading.IThreadPoolWorkItem.Execute()
         at System.Threading.ThreadPoolWorkQueue.Dispatch()
         at System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart()
         at System.Threading.Thread.StartCallback()
      --- End of stack trace from previous location ---

         --- End of inner exception stack trace ---
         at System.IO.Pipelines.StreamPipeWriter.FlushAsyncInternal(Boolean , ReadOnlyMemory`1 , CancellationToken )
         at SmtpServer.Protocol.QuitCommand.ExecuteAsync(SmtpSessionContext context, CancellationToken cancellationToken)
         at SmtpServer.SmtpSession.ExecuteAsync(SmtpCommand command, SmtpSessionContext context, CancellationToken cancellationToken)
         at SmtpServer.SmtpSession.ExecuteAsync(SmtpSessionContext context, CancellationToken cancellationToken)
         at SmtpServer.SmtpSession.RunAsync(CancellationToken cancellationToken)
         at SmtpServer.SmtpSessionManager.RunAsync(SmtpSessionHandle handle, CancellationToken cancellationToken)
tinohager commented 1 year ago

tcpdump

220 mail.testdomain.com v9.0.3.0 ESMTP ready
EHLO EUR03-DBA-obe.outbound.protection.outlook.com

250-mail.testdomain.com Hello EUR03-DBA-obe.outbound.protection.outlook.com, haven't we met before?
250-PIPELINING
250-8BITMIME
250 SMTPUTF8

MAIL FROM:<sender1@outlook.com> BODY=7BIT
RCPT TO:<test@testdomain.com>
DATA

250 Ok
250 Ok
354 end with <CRLF>.<CRLF>

XXXXXXXXXXXX
XXXXXXXXXXXX

.

250 Ok
QUIT
tinohager commented 11 months ago

Today I had a little time to analyze the issue again. During further tests I saw that the error only happens at hotmail/outlook at gmx.at/gmail it works without problems.

bogdanst24 commented 9 months ago

I am having the same issue

cosullivan commented 8 months ago

I suspect that some mail servers arent following the protocol correctly.

The handshaking here should be as follows;

What seems to be happening is that some mail servers are likely just sending the QUIT command and then disconnecting. In theory theres nothing wrong with that, but it doesnt follow the spec.

I'm trying to confirm this is actually what is happening and then can figure out the best way to approach this.

cosullivan commented 8 months ago

Here's the catch in the spec;

The sender MUST NOT intentionally close the transmission channel until it sends a QUIT command, and it SHOULD wait until it receives the reply

So SHOULD means that it doesnt need to if there is a good reason not too. I suspect that they dont wait because it could improve the performance of their systems ever so sligthly.

cosullivan commented 8 months ago

I've published 10.0.0-beta1 for now which includes this change.

cosullivan commented 8 months ago

Hi,

This should now be fixed in v10.0.0 which is now published. Please re-raise if the issue is still occuring.

Please note that there is a breaking change to the mailbox filter API but its a very easy modification for implementations.