cosullivan / smtpserver Goto Github PK
View Code? Open in Web Editor NEWA SMTP Server component written in C#
License: MIT License
A SMTP Server component written in C#
License: MIT License
I am using latest version(5.1) smtp server. i have add bcc mail address properly in when i send email from smtp client. but the smtp server could not find bcc address. I have tried from diffrent-2 code. but bcc is not getting me. My code is:
public class SmtpMessageStore : MessageStore
{
public override Task<SmtpResponse> SaveAsync(ISessionContext context, IMessageTransaction transaction, CancellationToken cancellationToken)
{
if (context.IsAuthenticated)
{
var textMessage = (ITextMessage)transaction.Message;
MimeMessage message = MimeMessage.Load(textMessage.Content);
}
}
}
}
So what should i do for get bcc address in mime message
I give up. I can't figure out how to create the server, add a user account, & send a message to that account.
Congratulations, this project is really nice.
Thank you.
I had many trouble (mainly nuget issues) to rebuild the solution with VS2017
(Microsoft Visual Studio Community 2017
Version 15.4.3
VisualStudio.15.Release/15.4.3+27004.2008
Microsoft .NET Framework
Version 4.7.02053)
but I suppose I've done it wrong.
I ended up to create a regular desktop project for the SmtpServer component, so it's ok for now.
Thanks again for this project.
The default .net SmtpClient produce an AUTH command recognized as invalid by SmtpServer.
The problem is in the base64 password which is not recognized as base64
Ex:
AUTH login bWF0dGVvQHBoYXNjb2RlLm9yZw==
I would like to use your SmtpServer to create a sort of 'intermediate' server, that allows me to do some preprocessing, if possible, once i receive emails. I start the server, using this code you provided:
var options = new OptionsBuilder()
.ServerName("localhost")
.Port(25, 587)
.Build();
var smtpServer = new SmtpServer.SmtpServer(options);
await smtpServer.StartAsync(CancellationToken.None);
but when send an email i got System.IO.IOException and System.Net.Sockets.SocketException.
Can you help me on this. Sorry for the NOOOB question.
Hi there,
Just done a clone and rebuild and there is a failure in building the MockMessageStore
public override Task<string> SaveAsync(ISessionContext context, IMimeMessage message, CancellationToken cancellationToken)
should be of type Task<SmtpResponse>
using System.Collections.Generic;
using System.Globalization;
using System.Threading;
using System.Threading.Tasks;
using SmtpServer.Mail;
using SmtpServer.Storage;
namespace SmtpServer.Tests.Mocks
{
public class MockMessageStore : MessageStore
{
readonly List<IMimeMessage> _messages = new List<IMimeMessage>();
public override Task<string> SaveAsync(ISessionContext context, IMimeMessage message, CancellationToken cancellationToken)
{
_messages.Add(message);
return Task.FromResult(_messages.Count.ToString(CultureInfo.InvariantCulture));
}
public List<IMimeMessage> Messages
{
get { return _messages; }
}
}
}
Hello,
Please could you push v2.0.0-Beta1 to nuget.org as its the current version in master?
In future, could a branching structure of develop/master be used so master is always the latest stable and develop being the awesome new stuff or something like this?
Thanks
Example:
220 mail.xx v4.3.0.0 ESMTP ready
HELO localhost
250 Hello localhost, haven't we met before?
MAIL FROM:<>
553 mailbox name not allowed //the error message is shown via CanAcceptFromAsync method, but it lets the session proceed
RCPT TO:<[email protected]>
250 Ok
DATA
...
E.g. if you use only an empty recipient name, it works fine (501 syntax error).
(As a workaround, I check the same conditions in CanDeliverToAsync() again, so the sender can at least be blocked here)
Hey again,
It just struck me: How do I access the SMTP envelopes From & To properties?
The IMimeMessage
interface exposes a From
(single IMailBox
) and a To
(list of IMailBox
) - are these the SMTP from/to?
Maybe they should be named EnvelopeFrom
and EnvelopeTo
?
Hi @cosullivan, how are you?
I got a problem with some emails that I received on the server and I'm doubtful if it could be a component error.
I noticed some e-mails presenting errors in signatures, images, font size and others, checking the cases, all at first seemed to present the lack of a dot (".") In some part of the e-mail.
Some cases the email would be in the first position of the next line.
I noticed this piece of code in the system I would like to understand if it might be related:
{
// need to trim the '.' At the start of the line if it
// exists this would have been added for transparency
// http://tools.ietf.org/html/rfc5321#section-4.5.2
Context.Transaction.Mime.AppendLine (text.TrimStart ('.'));
}
If I understood correctly, the excerpt "text.TrimStart ('.')" Will remove the point if this is the first character of the line. From what I've seen in my EMLs, the problem must be just that.
Verifying your comment, I did not understand if the indicated "period" of the text to be removed should even be a point, and if yes, I did not understand the logic.
Could you help me to understand this point better?
Thank you
Hi,
Is there a changelog? If not, please create them or use GitHub milestones/releases.
Thanks for the awesome lib! Used it with pleasure in an unit test for NLog :)
When receiving a large number of messages over a short period of time (e.g. 250,000 messages over a period of 2 minutes,) I am seeing very high CPU usage (95%+) and memory usage (3 GB+.) The server initially accepts messages quickly but then slows down to the point of accepting only one message every few seconds.
Profiling showed contention related to TaskExtensions.WithTimeout()
's usage of Task.Delay()
.
I'm using .NET Core 2.0 on Windows 10 x64. My application is doing almost nothing - just calling Interlocked.Increment()
to track the amount of messages it receives, so I don't suspect any code in my application.
I'm using this library in an unit test.
What's the best pattern to use this? It's not fully clear to me when I could start reading.
Currently I have this: (full code)
var countdownEvent = new CountdownEvent(1);
... //create SMTP server
smtpServer.StartAsync(cancellationToken.Token);
... //send mail
countdownEvent.Wait(TimeSpan.FromSeconds(10)); //wait max 10 sec
...//do assertions
cancellationToken.Cancel(false); //done, cancel for new test
It works, but it's a bit unstable.
Thanks for your advise!
Hi
Thank you for your great work. I notice that there is no develop branch and your last commit is WIP.
It is not better to work on develop branch and keep master branch stable.
Best regards.
Hi,
I just experienced that simple test emails, e.g. with no text or only one line, are not processed.
E.g. this telnet example works fine:
...
250 Ok
DATA
354 end with <CRLF>.<CRLF>
asdf
asdf
.
Removing one "asdf" line results in a neverending telnet window with no more response:
...
DATA
354 end with <CRLF>.<CRLF>
asdf
.
.
Could you give me some information about this issue?
Thank you,
best regards
RFC8314 brings back port 465 for always-encrypted SMTP traffic - something that used to exist, went away, and has now been standardized again.
I wonder if you could see something like this working:
var builder = new OptionsBuilder()
....
.Certificate(GetTheCert())
.Port(25)
.SecurePort(465)
.Build()
The implementation would be along the lines of changing SmtpSessionContext:31
and wrapping the existing stream in an SSLStream created by calling AuthenticateAsServerAsync
along with the X509 certificate that was also passed in.
Is this format supported?
no reply <[email protected]>
e.g. Mime.ToString()
From: [email protected]
Date: Thu, 01 Jun 2017 19:02:17 +0200
Subject: Message from NLog on DELL-JULIAN
Message-Id: <[email protected]>
To: [email protected]
Cc: no reply <[email protected]>
But DisplayName
is null
We are using your wonderful server. Thank you very much!
We wanted to ask you if you can make a VS 2015 with .Net (not core) version...?
Since you moved to 2017 we cannot use your server since we do not work with .Net Core nor VS 2017
Hey,
While testing, I start and stop my server a lot. I've found that once in a while, when the server starts, it will drop the first connection.
I'm unsure what causes this - as the server runs fine for long periods of time. In the picture, I run the server two times. The first receives 10 messages without issue, but then it's restarted and suddenly the first message connection is closed by the server.. Messages after that initial closed connection will do fine.
I could dig deeper, but I'm out of time right now.
Hi,
sorry this is not a real issue - just a question:
I only want to allow SSL connections on the server. How can I check, whether the connection is secure and the mail is coming over SSL on the server side?
Thank you for your help.
Best regards,
Bernhard E
At the moment I'm sending a lot of mails concurrently - heavy load test.
I create 100 mails and send them in 3 seconds by using an external smtp server. Only about the half is receiving. For the other half I got errors 501
550 5.0.350 Remote server returned an error -> 501 expected NOOP/RSET/QUIT/RCPT/DATA, 4 retry(ies) remaining.
In my log I can see that the MailFilter is called successfully all the time (100 times), but the MessageStore is not called.
Any idea?
Thanks, Bernhard
Are you guys planning to add relay support to smtpserver?
I also didnt find any dns mx lookup class to forward mails to the right mail servers.
When SmtpServer receive EML with special chars, lib broke chars and chage that to "?" instead.
Characteres are broked in Subject and Body.
How to reproduce:
Attach, follow the EML file to test.
Hello, Is there a way users can bypass authentication when coming from localhost?
thanks
Is it possible to get the IP address of the sender of an email that gets received by this smtp server?
Hi,
first thank you so much for your great work.
I'm trying to get your sample project working with SSL enabled but I'm failing.
//smtpClient.EnableSsl = true;
EnableSsl does not exists any more
I tried also ConnectSSL and StartTls - both failing, could you please update your sample or provide some information about what is going wrong?
Thanks, Bernhard
Hello, I love this project. I was using an older version of this (1.2.2.0) with no issues. I'm working on updating my project and with v1.6 I can't get the MessageStore option to work. It is saying that it only takes IMessageStoreFactory as its argument. I tried changing my ConsoleMessageStore to an IMessageStoreFactory, but it told me 'WindowsService1.ConsoleMessageStore' does not implement interface member 'SmtpServer.Storage.IMessageStoreFactory.CreateInstance(SmtpServer.ISessionContext)'
Any suggestions on how to work around this?
This is a great project, thanks sharing ! Anyway have you thought about a SpamAssassin integration (over TCP) or to you rather think it's better to put a Postfix + Amavisd in front of this C# SmtpServer to handle filtering ?
We are looking at using it to provider inbound e-mail web hooks (we are aware that there are SendGrid, Mailgun that provides inbound web hooks but we prefer to run it closer "to our infrastructure").
I copied your example code exactly and it is not calling my custom authenticator.
var options = new OptionsBuilder()
.ServerName("localhost")
.Port(25, 587)
.MessageStore(new ConsoleMessageStore())
.MailboxFilter(new MailboxFilterFactory())
.UserAuthenticator(new UserAuthenticator())
.Build();
var smtpServer = new SmtpServer.SmtpServer(options);
await smtpServer.StartAsync(CancellationToken.None);
Then,
public class UserAuthenticator : IUserAuthenticator
{
public Task<bool> AuthenticateAsync(string user, string password)
{
Console.WriteLine("User={0} Password={1}", user, password);
return Task.FromResult(user.Length > 4);
}
}
Console debug line is never displayed and breakpoints are never hit. I'm sending the messages with:
using (var client = new SmtpClient(host, port))
{
client.Credentials = new System.Net.NetworkCredential("yourusername", "yourpassword");
client.UseDefaultCredentials = false;
await client.SendMailAsync(FakeMessage);
}
Please advise.
Hi,
I was looking for a good C# SMTP server for a small project, and lo and behold. This looks really great.
I'm lacking a little on the hooks though, as the MessageStore seems to lack a number of things. All it really has access to is the actual message itself - not the IP f.ex. For my project, I need to store the IP of the remote client sending data.
For extra points, I'd love to store the commands sent/received in a specific session as well. But that's for another day.
I was playing around a little, and I added the EndPoint
to ISmtpSessionContext
. When it's created by SmtpSession
, I then grab the TcpClients
remote endpoint and store it. SaveAsync
for the message can then be extended to include the remote endpoint. But I'm unsure if this is the best way.
In order to extend it, it might make sense to create a "context" (or extend the existing) which then contains this info. Thoughts?
Mike.
Hi,
in rare cases it happens that unhandled exceptions (caused e.g. by myself) are thrown while I am processing emails, e.g. in the SaveAsync method.
I try to catch all possible exceptions, but for reasons I cannot really reproduce some of them are not caught and this results e.g. in a not responding SmtpServer.
Ttelnet'ing the server afterwards shows no welcome message etc. any more, but it also does not refuse the connection - so I would like to be able to restart the SmtpServer in such a case.
Because of the async type a try/catch block around server.StartAsync() would not help, of course.
Are there maybe some options etc. I can pass to the server before I start it?
In short, it would be great if I could simply restart the server on any exception (or catch and log every exception and let the server continue).
Thank you
We send the mail from client and its will get on server. When server executed so how to return message on client when facing some exception in smtpserver and how to client to know that what was my response
Hi,
When we send an email using "Thunderbird" and sending the email with non-English encoding (for example Russian), the mail that reaches the client is in gibberish and not as it was originally written.
I think there is a bug in the way the server handles the encoding part.
I couldn't find a way to fix this.
How to know if the context is authenticated ? (and maybe the relative username)
Would it be possible to add functionality into SmtpServerOptionsBuilder to enforce usage of forced TLS (and not opportunistic)?
Using your SMTP server, I can send a message?
Hi,
Thank you for your great SmtpServer. We have been using it quite some time.
We encountered an issue with the Smtp Server that we wanted to consult with you.
In SmtpCommand.cs
while ((text = await context.Text.ReadLineAsync(TimeSpan.FromSeconds(60), cancellationToken).ConfigureAwait(false)) != ".")
{
// need to trim the '.' at the start of the line if it
// exists as this would have been added for transparency
// http://tools.ietf.org/html/rfc5321#section-4.5.2
**context.Transaction.Mime.AppendLine(text.TrimStart('.'));**
}
We think that the above highlighted code causes the below problem.
Problem:
When mime part is text/html and the CRLF is located right after the numeric part of the font size declaration,
removing the first period in the following line causes the font to be bigger.
For Example:
Original mail:
le=3D'font-size:11.0pt;font-family:"Calibri",sans-serif;color:windowtext'>=
Outlook<span style=3D'font-size:11.
0pt;font-family:"Arial",sans-serif;color:windowtext'></sp=
After parsing we receive the mail with bigger font:
le=3D'font-size:11.0pt;font-family:"Calibri",sans-serif;color:windowtext'>=
Outlook<span style=3D'font-size:11=
0pt;font-family:"Arial",sans-serif;color:windowtext'></sp=
The " ." has been lost.
This causes the font size to be suddenly bigger
The way found to fix this is as follow:
while ((text = await context.Text.ReadLineAsync(TimeSpan.FromSeconds(60), cancellationToken).ConfigureAwait(false)) != ".")
{
string tmp = text;
if (text.Length > 0 && text[0] == '.')
tmp = text.Substring(1);
context.Transaction.Mime.AppendLine(tmp);
// need to trim the '.' at the start of the line if it
// exists as this would have been added for transparency
// http://tools.ietf.org/html/rfc5321#section-4.5.2
//context.Transaction.Mime.AppendLine(text.TrimStart('.'));
}
We would appreciate your thoughts about this issue.
Looks like a wired up IUserAuthenticator doesn't actually get used. Can you add a unit test so that I can validate my implementation, as well as validating the code works? I'm doing a fairly simple SmtpClient.Credentials = new System.Net.NetworkCredential("testuser", "testpass"), but the
AuthenticateAsync(string, string)` method is never called.
I got the error "Transaction failed. The server response was: " at line 92 of Program.cs:
https://github.com/cosullivan/SmtpServer/blob/master/Src/SampleApp/Program.cs#L92
Can you please explain it.
Thank you
Firstly, I really like what you've done with this :)
I think, MaxMessageSize should be taken into account while the message is being received, it should stop accepting anymore of the message if it reaches the maximum size. Currently, I have put a check into my implementation of IMessageStore, but by the time that is called the message is already fully received.
Hi,
I am looking for the simplest way for saving a full log of communications between 2 servers (HELO, DATA etc.), and assign it to the received message.
So basically I would need the MessageID and another string which contains the whole log for this message (e.g. like it looks via telnet).
Are events like OnSessionCreated, OnCommandExecuting and OnSessionCompleted the right approach to achieve this?
Or is there maybe an easier "built-in" way to get full logs for the mail transactions?
Thank you!
Hi,
is there any way for taking the incoming mail and send it to another smtp server?
regards, Andrea Pirola
We are trying to use the server as a nuget in Visual Studio 2015 and we get an error:
Error: System.IO.FileLoadException: Could not load file or assembly 'SmtpServer, Version=4.1.1.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. A strongly-named assembly is required. (Exception from HRESULT: 0x80131044)
File name: 'SmtpServer, Version=4.1.1.0, Culture=neutral, PublicKeyToken=null'
Is there a workaround except downloading the entire source?
Hi .. i already fork and add some initial code to work with Cassandra as storage db
Hey,
I was looking into migrating the SmtpServer projects to Core. And most of it is just easy-peasy straight ahead. I've discovered issues with a few things:
Close()
or Dispose()
(which I find odd) in netcoreapp1.0
SslProtocols
doesn't have a Default
memberAssembly
from a Type (it's now a TypeInfo
)I could commit my changes, if it were something of interest?
Hi,
is it possible to retrieve the Message-Id of the message in a custom MessageStore module (or in any other module)?
regards, Andrea
If authentication is required , client connection is aborted when user attempts to login.
Can be easily reproduced in SessionContextExample sample code, just by requiring authentication in options.
Can fix like:
void OnSessionAuthenticated(object sender, EventArgs eventArgs)
{
_context.SessionAuthenticated -= OnSessionAuthenticated;
WaitingForMail.Clear(AuthCommand.Command);
WaitingForMailSecure.Clear(AuthCommand.Command);
if (_options.AuthenticationRequired)
{
// << PATCH
WaitingForMail.Clear(MailCommand.Command);
WaitingForMailSecure.Clear(MailCommand.Command);
// PATCH >>
WaitingForMail.Add(MailCommand.Command, TryMakeMail, SmtpState.WithinTransaction);
WaitingForMailSecure.Add(MailCommand.Command, TryMakeMail, SmtpState.WithinTransaction);
}
}
Or, better, get State.Add to work as (currently unused) State.Replace in all cases. This also fixes another problem, as currently multiple emails per-session cannot be sent. E.g.
HELO xxx
MAIL FROM: <[email protected]>
RCPT TO: <[email protected]>
DATA
...
RSET
MAIL FROM: <[email protected]>
Playing around with actual mail systems (Google, Microsoft), I've noticed something: They don't seem to think a mail was safely delivered.
Looking at wireshark, I noticed that there seems to be lacking a final "250 OK" (or similar) from the server after receipt. I tried changing the returned value from SaveAsync
to be "250 OK", but this value doesn't appear in the TCP stream.
Am I doing something wrong?
I can't find any information on how to set any time outs. I have a bad client that consistently sends the DATA command, then doesn't send anything after that. The server just sits and waits forever, wasting resources. I have to reset it manually. I'd like to be able to set it to so many milliseconds, say 2 minutes worth, and then the system sends a 501 and closes the session.
https://tools.ietf.org/html/rfc2821#section-4.5.3.2
See RFC 2821 Section 4.5.3.2
An SMTP client MUST provide a timeout mechanism. It MUST use per-
command timeouts rather than somehow trying to time the entire mail
transaction. Timeouts SHOULD be easily reconfigurable, preferably
without recompiling the SMTP code. To implement this, a timer is set
for each SMTP command and for each buffer of the data transfer. The
latter means that the overall timeout is inherently proportional to
the size of the message.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.