Delayed send with smtpclient in .net 2.0
- Is there any way to force the smtpclient to send mail immediately with the .send method in system.net.mail 2.0? Right now it takes anywhere from 90 secods to two minutes before the mail is actually sent once the .send method executes. I've tried setting the object to nothing immediately after the .send method call, but no luck.
The real issue for me is the send delay is also causing the smtpclient to hold a lock on attached files that are being sent for that same 90 seconds to two minutes. I need to move the file immediately after emailing it, and right I get an exception telling me two processes can't access the file at the same time - obviously the smtpclient holding onto the file until it's ready to sent it. BTW, this app was using system.web.mail with none of these issues - I'm trying to upgrade it to 2.0.
Thanks,
Geoff
Answers
For anyone interested, I've found a solution or at least a work around to the delay.
The ServicePoint member contains a member called MaxIdleTime. Setting this value to 0 seems to have the same affect as Timeout.Infinite (which I assume is also 0). Setting it to 1 caused my email to be sent out immediately.
See this link:
http://msdn2.microsoft.com/en-us/library/system.net.servicepoint.maxidletime.aspx
Example code:
SmtpClient smtp = new SmtpClient();
// setup the mail message
smtp.ServicePoint.MaxIdleTime = 1;
smtp.Send(myMailMessage);
- Ok, I found the problem with the file handle not being released. Turns out that disposing either the MailMessage object or the Attachment object frees up the stream that is holding onto the file (which makes sense, but I am not sure why calling GC.Collect didn't result in this problem going away).
Please give it a try and let me know what you find.
All Replies
- Could you add some code snippets on how you use SmtpClient? Also, could you enable trace logging and send it to me? What type of SMTP server are you sending e-mail through? What speed connection are you on? I would like to understand more about your environment so that I can try to help you figure out what is going on.
See http://blogs.msdn.com/dgorti/archive/2005/09/18/471003.aspx for information on enabling trace logging. - That said, SMTP is unlike real time (depending on your interpretation) protocol like
HTTP and FTP. SMTP is a store and forward protocol. It may take any amount of time. Usually we are used to speedy links and hence your email may appear instantaneous - but it can take an arbitrary time.
What is more important to know - is if the mail is leaving your machine. That you can easily infer by tracing using the blog entry jon has pointed out. Or Just use a regular network monitor
Thanks - Sorry guys, I really didn't provide enough info on my environment.
I'm sending mail to an Exchange server on my local network, so it's a 100Mb link straight to an internal Exchange server. The mail is not leaving my machine during the delay, and I can force the mail to be sent immediately by stopping the debug session. Below is the code that's generating and sending the mail.
I need to move the attached file immediately after sending the mail, and because of the delay I'm getting an execption on the file.move at the end as the smtpclient still has a lock on the file.
Geoff
' Send the message
Me.Cursor = Cursors.WaitCursor
' send the message using the data in the UI controls for the envelope metadata
' so the user can change destination address, subject, etc.
Try
Dim oFromAddr As New System.Net.Mail.MailAddress("xxxxx@yyyyy.com", "Mail Forwarding Service")
Dim oToAddr As New System.Net.Mail.MailAddress(Me.txtTo.Text)
Dim mailMsg As New MailMessage(oFromAddr, oToAddr)
Dim oAttach As New Attachment(oMessage.Filename, "message/rfc822")
oAttach.Name = oMessage.Subject
mailMsg.Subject = Me.txtSubject.Text
mailMsg.Body = Me.rtbReason.Text
mailMsg.Attachments.Add(oAttach)
Try
Dim osmtpClient As New SmtpClient
osmtpClient.Host = "mail1.xxxxxx.com"
osmtpClient.Send(mailMsg)
' close everything to release mail
oAttach = Nothing
mailMsg = Nothing
osmtpClient = Nothing
Catch ex As Exception
MessageBox.Show("Sending Failed... Check the To: Address", Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
Catch
MessageBox.Show("Error Creating Mail Message", Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Error)
Exit Sub
End Try
' move the attachment file to the finished directory
Try
Dim sDest As String = ""
sDest = Regex.Replace(oMessage.Filename, "(Header|Keyword|RBL|URI|Harvesting|Bayesian|Deferred)", "Finished", RegexOptions.Compiled Or RegexOptions.IgnoreCase)
File.Move(oMessage.Filename, sDest)
Catch
MessageBox.Show("Error moving sent message file.", Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
gm001 wrote: The mail is not leaving my machine during the delay, and I can force the mail to be sent immediately by stopping the debug session.
Can you explain this a little more? What do you mean by "stopping the debug session"? Are you broken into a debugger or just have a debugger attached? What happens if you don't have a debugger attached? Do you still get the delay?- What I meant was that if I run the app in VS with no breakpoints and perform an action that causes a message to be sent, I get the delay. If I stop the app during the delay period the mail is immediately sent as the app closes. Same thing holds true if I run the .exe outside of VS. Seems like it needs the GC to run before it will send the message.
Geoff
- What if you put the following code right after you call Send()? Note that this is not recommended for your application except for debugging purposes.
GC.Collect();
GC.WaitForPendingFinalizers();
- No joy. Still waits for the same amount of time or until I close the app. Guess that kills the GC theory.
Geoff
Were you able to get a trace log of the problem? Here is the app.exe.config file I would use:
<?xml version="1.0" encoding="UTF-8" ?><configuration>
<system.diagnostics>
<trace autoflush="true" />
<sources>
<source name="System.Net">
<listeners>
<add name="System.Net"/>
</listeners>
</source>
<source name="System.Net.Sockets">
<listeners>
<add name="System.Net"/>
</listeners>
</source>
</sources>
<sharedListeners>
<add
name="System.Net"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="System.Net.trace.log"
traceOutputOptions = "DateTime"
/>
</sharedListeners>
<switches>
<add name="System.Net" value="Verbose" />
<add name="System.Net.Sockets" value="Verbose" />
</switches>
</system.diagnostics>
</configuration>
Also, just as a note, you should make sure that you scan that trace log and make sure any private information is removed before posting it.- Thanks for the config. Very interesting results. Here's the tail of the log file, after the last part of message is sent.. Take a look at the last two entires, especially the timestamps. The mail conversation with the exchange server doesn't appear to end with the normal smtp "quit" command, and until the socket dispose you see in the log, the mail doesn't get delivered. It's almost as if .net wants to pool the connection and keep it open in case there's more mail to send. So now that I see the behavior, how do I change it? Some magical setting in a config file somewhere??
Thanks,
Geoff
... System.Net.Sockets Verbose: 0 : [3460] Socket#13951800::Send()
DateTime=2005-12-12T21:16:11.3153184Z
System.Net.Sockets Verbose: 0 : [3460] Data from Socket#13951800::Send
DateTime=2005-12-12T21:16:11.3309431Z
System.Net.Sockets Verbose: 0 : [3460] 00000000 : 0D 0A 2D 2D 2D 2D 62 6F-75 6E 64 61 72 79 5F 30 : ..----boundary_0
DateTime=2005-12-12T21:16:11.3778172Z
System.Net.Sockets Verbose: 0 : [3460] 00000010 : 5F 65 32 62 30 33 31 31-31 2D 30 65 36 30 2D 34 : _e2b03111-0e60-4
DateTime=2005-12-12T21:16:11.3934419Z
System.Net.Sockets Verbose: 0 : [3460] 00000020 : 39 35 35 2D 38 32 37 64-2D 32 34 65 38 36 38 39 : 955-827d-24e8689
DateTime=2005-12-12T21:16:11.4246913Z
System.Net.Sockets Verbose: 0 : [3460] 00000030 : 65 35 32 38 39 2D 2D 0D-0A : e5289--..
DateTime=2005-12-12T21:16:11.4403160Z
System.Net.Sockets Verbose: 0 : [3460] Exiting Socket#13951800::Send() -> 57#57
DateTime=2005-12-12T21:16:11.4559407Z
System.Net.Sockets Verbose: 0 : [3460] Socket#13951800::Send()
DateTime=2005-12-12T21:16:11.4715654Z
System.Net.Sockets Verbose: 0 : [3460] Data from Socket#13951800::Send
DateTime=2005-12-12T21:16:11.4871901Z
System.Net.Sockets Verbose: 0 : [3460] 00000000 : 0D 0A : ..
DateTime=2005-12-12T21:16:11.5028148Z
System.Net.Sockets Verbose: 0 : [3460] Exiting Socket#13951800::Send() -> 2#2
DateTime=2005-12-12T21:16:11.5184395Z
System.Net.Sockets Verbose: 0 : [3460] Socket#13951800::Send()
DateTime=2005-12-12T21:16:11.5340642Z
System.Net.Sockets Verbose: 0 : [3460] Data from Socket#13951800::Send
DateTime=2005-12-12T21:16:11.5496889Z
System.Net.Sockets Verbose: 0 : [3460] 00000000 : 0D 0A 2E 0D 0A : .....
DateTime=2005-12-12T21:16:11.5653136Z
System.Net.Sockets Verbose: 0 : [3460] Exiting Socket#13951800::Send() -> 5#5
DateTime=2005-12-12T21:16:11.5965630Z
System.Net.Sockets Verbose: 0 : [3460] Socket#13951800::Receive()
DateTime=2005-12-12T21:16:11.6121877Z
System.Net.Sockets Verbose: 0 : [3460] Data from Socket#13951800::Receive
DateTime=2005-12-12T21:16:11.6278124Z
System.Net.Sockets Verbose: 0 : [3460] 00000000 : 32 35 30 20 4D 61 69 6C-20 71 75 65 75 65 64 20 : 250 Mail queued
DateTime=2005-12-12T21:16:11.6434371Z
System.Net.Sockets Verbose: 0 : [3460] 00000010 : 66 6F 72 20 64 65 6C 69-76 65 72 79 2E 0D 0A : for delivery...
DateTime=2005-12-12T21:16:11.6590618Z
System.Net.Sockets Verbose: 0 : [3460] Exiting Socket#13951800::Receive() -> 31#31
DateTime=2005-12-12T21:16:11.6746865Z
System.Net Verbose: 0 : [3460] Exiting SmtpClient#66753006::Send()
DateTime=2005-12-12T21:16:11.6903112Z
System.Net.Sockets Verbose: 0 : [5636] Socket#13951800::Dispose()
DateTime=2005-12-12T21:17:44.7978985Z
- I have created an in-house repro of this problem. Let me investigate and I will let you know what I find.
- Great, thanks.
Geoff
- Ok, I found the problem with the file handle not being released. Turns out that disposing either the MailMessage object or the Attachment object frees up the stream that is holding onto the file (which makes sense, but I am not sure why calling GC.Collect didn't result in this problem going away).
Please give it a try and let me know what you find. - Disposing the Attachment ojbect fixes the file handle issue, thanks!
I take it you were also able to repro the delayed sending, and that's something you're still looking into?
BTW, tracing is sweet.What a great addition to the framework.
Thanks,
Geoff
- No, I didn't get the delayed send problem in house. Can you e-mail me the entire trace log?
Also, can you work on getting a network sniff for me? See this blog for information on netmon usage. Please e-mail it to me when you have it. - I am getting the same behavior. The mail is delayed. Anything new on this topic? MSDN no luck, even Google nothing.
Thank you Jan, Please note that the connection need not be closed for mail to be sent.
You need to get a NETMON capture for really understanding what EXACTLY is going on the wireThanks
Just thought I'd let you know I'm getting exactly the same problem with the .NET 2.0 framework using an ASP.NET application and an e-mail with no attachments. The SMTP server log seems to indicate that the .NET framework does not send a 'QUIT' message, and so it does not send the mail until the connection times out. You can see a huge delay after the first RCPT. I've tried turning on tracing as described earlier but cannot find a log file anywhere on my system!
Here's the SMTP server log file,
Damien
#Software: Microsoft Internet Information Services 5.1
#Version: 1.0
#Date: 2006-01-05 19:40:16
#Fields: time c-ip cs-method cs-uri-stem sc-status
19:40:16 127.0.0.1 EHLO - 250
19:40:16 127.0.0.1 MAIL - 250
19:40:16 127.0.0.1 RCPT - 250
19:41:56 127.0.0.1 MAIL - 250
19:41:56 127.0.0.1 RCPT - 250
19:41:56 127.0.0.1 DATA - 250
19:41:56 - - - 0
19:41:56 exim8.blueyonder.co.uk EHLO - 0
19:41:56 exim8.blueyonder.co.uk - - 0
19:41:56 exim8.blueyonder.co.uk MAIL - 0
19:41:56 exim8.blueyonder.co.uk - - 0
19:41:56 exim8.blueyonder.co.uk RCPT - 0
19:41:56 exim8.blueyonder.co.uk - - 0
19:41:56 exim8.blueyonder.co.uk DATA - 0
19:41:56 exim8.blueyonder.co.uk - - 0
19:41:56 exim8.blueyonder.co.uk - - 0
19:41:56 exim8.blueyonder.co.uk QUIT - 0
19:41:56 exim8.blueyonder.co.uk - - 0
19:41:58 127.0.0.1 QUIT - 0Doh! Didn't realise the log file output went to the output window, that's just a bit too easy....
Here's the last part of the log. If you look at the last 2 lines there is a huge delay between the final send (second to last line) and the 'dispose' on the last line. As soon as the 'dispose' is executed the e-mail actually gets sent. Strange why is waits, if anyone knows, let me know!
Cheers
Damien
System.Net.Sockets Verbose: 0 : [0380] Exiting Socket#30180123::Send() -> 96#96
System.Net.Sockets Verbose: 0 : [0380] Socket#30180123::Send()
System.Net.Sockets Verbose: 0 : [0380] Data from Socket#30180123::Send
System.Net.Sockets Verbose: 0 : [0380] 00000000 : 0D 0A : ..
System.Net.Sockets Verbose: 0 : [0380] Exiting Socket#30180123::Send() -> 2#2
System.Net.Sockets Verbose: 0 : [0380] Socket#30180123::Send()
System.Net.Sockets Verbose: 0 : [0380] Data from Socket#30180123::Send
System.Net.Sockets Verbose: 0 : [0380] 00000000 : 0D 0A 2E 0D 0A : .....
System.Net.Sockets Verbose: 0 : [0380] Exiting Socket#30180123::Send() -> 5#5
System.Net.Sockets Verbose: 0 : [0380] Socket#30180123::Receive()
System.Net.Sockets Verbose: 0 : [0380] Data from Socket#30180123::Receive
System.Net.Sockets Verbose: 0 : [0380] 00000000 : 32 35 30 20 4D 61 69 6C-20 71 75 65 75 65 64 20 : 250 Mail queued
System.Net.Sockets Verbose: 0 : [0380] 00000010 : 66 6F 72 20 64 65 6C 69-76 65 72 79 2E 0D 0A : for delivery...
System.Net.Sockets Verbose: 0 : [0380] Exiting Socket#30180123::Receive() -> 31#31
System.Net Verbose: 0 : [0380] Exiting SmtpClient#34678979::Send()
System.Net.Sockets Verbose: 0 : [3460] Socket#30180123::Dispose()
- I'm having the same issue. Wondering what the status is on this, if anyone has figured out a solution or work around to force the mail to be sent out immediately rather than later.
For anyone interested, I've found a solution or at least a work around to the delay.
The ServicePoint member contains a member called MaxIdleTime. Setting this value to 0 seems to have the same affect as Timeout.Infinite (which I assume is also 0). Setting it to 1 caused my email to be sent out immediately.
See this link:
http://msdn2.microsoft.com/en-us/library/system.net.servicepoint.maxidletime.aspx
Example code:
SmtpClient smtp = new SmtpClient();
// setup the mail message
smtp.ServicePoint.MaxIdleTime = 1;
smtp.Send(myMailMessage);
Well done! I've just tried it here and the mail was sent immediately.
However....I did notice that after sending the CPU was permanently at 50%, and looking at the processes it was 'aspnet_wp.exe'. I couldn't see what it was doing though. This did not happen before I added the line to set MaxIdleTime to 1.
Since MaxIdleTime is in milliseconds I set it to 1000 (1 second) and now it all seems to work fine. Mail gets sent within 1 second, and aspnet_wp.exe returns to negligible CPU after.
Can't explain it, but at least it seems to work.
Thanks jptros,
Damien
- My problems with the delayed send was solved when I turned off Norton Antivirus outgoing emailscan. After turning it off the email was sent at once and not after my program had exited.
- not sure if anyone is continuing to check this thread, but i'm still having the delayed sending problem even after switching the MaxIdleTime in the ServicePoint member to 0, 1, and 1000. I am using Norton Antivirus, and disabling Norton Internet Security causes the message to be sent immediately. Does anyone have any other suggestions for sending a message immediately other than MaxIdleTime?
Hi,
Setting MaxIdleTime to 1000 solved the problem for me. My Symantec AV scans the message emediately after sending.
Thanks,
Charl
I noticed this thread, it helped me, thought I'd post back my function that seems to overcome the issue, even with Symantec scanning enabled. Hope it helps someone. The 2 servicepoint entries are really the fix, the mail gets sent immediately.
Public Function SendMail(ByVal Msg As System.Net.Mail.MailMessage)Mailer.Host = PrimarySMTPHost
Mailer.DeliveryMethod = Net.Mail.SmtpDeliveryMethod.Network
Mailer.ServicePoint.MaxIdleTime = 1
Mailer.ServicePoint.ConnectionLimit = 1
Dim MailError As New System.Net.Mail.SmtpException TryMailer.Send(Msg)
Return "OK" Catch MailErrorMailer.Host = SecondarySMTPHost
Mailer.Send(Msg)
Return MailError.Message End Try End Function- I have been a member of MSDN for quite a while but have never used the forums as I don't write very sophistcated code, so I'm not familiar with the process. If this is the wrong place to submit this post, I would appreciate it if you would let me know.
Having said that, I saw this old thread and it seems to apply to a problem I am currently having.
I have an app that sends mail from remote users using our Exchange 2003 server as the host.
My code is really basic.
I have read through the posts in this thread and tried all the resolutions that I understood. None of them seem to work.
I have Symantec End Point Protection installed on the client. It is apparently blocking the email. If I disable it the email goes out right away.
I am hoping this has been enough of a problem that there may be some more recent resolution.
This is the code I am currently testing.
Thanks in advance for any help you can provide.
Try SiToMBodyString = Me.tbJobNumber.Text & ": " & Me.tbJobName.Text & " field inspection information has been UPDATED as of " & Format(Now, "Short Date") & " at " & Format(Now, "Short Time") T19InspItemsRetValT19InspItemsRetVal = T19InspItemsRetVal & _ Chr(13) & Chr(13) & _ "The Total elapsed time was " & ElapsedTime.ToString & "." ' mail Me.labPleaseWait.Visible = True Me.labPleaseWait.Text = "Preparing mail to send to office." Application.DoEvents() Dim SentFromString As String = Environment.UserName & "@Jmcfire.com" 'EmailAddress Dim SendToString As String = "sda@jmcfire.com" Dim SiToMSubjectString As String = _ "Field Inspection Info Sent To Office On " & Format(Now, "Short Date") Dim JmcFire_Client As New Mail.SmtpClient SiToMBodyStringSiToMBodyString = SiToMBodyString & Chr(13) & Chr(13) & _ T19InspItemsRetVal JmcFire_Client.Credentials = Me.CardenCredentialCache 'CwService.Credentials JmcFire_Client.Host = "mail.jmcfire.com" JmcFire_Client.Port = 25 JmcFire_Client.ServicePoint.MaxIdleTime = 0 JmcFire_Client.DeliveryMethod = Mail.SmtpDeliveryMethod.Network Dim InspNotificationMessage As New Mail.MailMessage(SentFromString, SendToString) With InspNotificationMessage .Subject = SiToMSubjectString .Body = SiToMBodyString End With JmcFire_Client.Send(InspNotificationMessage) 'JmcFire_Client.Send(SentFromString, SendToString, SiToMSubjectString, SiToMBodyString) InspNotificationMessage.Dispose() InspNotificationMessage = Nothing JmcFire_Client = Nothing MsgBox(SiToMBodyString & Chr(13) & Chr(13) & _ "A confirming email will be been sent to the office with the same information contained in this message!") Catch ex As Exception MsgBox(ex.Message & " From: Send Mail.") End Try - Proposed As Answer byVulkan Thursday, April 09, 2009 6:44 PM
- Sooo after much messing around since i use Symantec Endpoint here as welli have figured this out...SMTP.ServicePoint.MaxIdleTime = 1000;SMTP.ServicePoint.ConnectionLimit = 1;SMTP.ServicePoint.UseNagleAlgorithm = true;setting tho's three options forces my mail to send imediatly.i've been messing around with this for days looking for an answer this worked for me, the only addition to the above methods was the UseNagleAlgorithm

