• [C#] Email not being sent when using "using" statement
    13 replies, posted
Sends fine without the wrapped using statements, unfortunately it doesn't dispose of the file, hence why it's wrapped. Also the second parameter of "SendAsync" is supposed to be a callback after the message is sent? I tried putting "SendCompletedCallback" in there and I get errors. Also, C# lvl 1 here, this is mostly snippets and little of my work. Feel free to critique if there is anything wrong. [CODE]using (SmtpClient ss = new SmtpClient("smtp.gmail.com", 587)) { ss.EnableSsl = true; ss.Timeout = 10000; ss.DeliveryMethod = SmtpDeliveryMethod.Network; ss.UseDefaultCredentials = false; ss.Credentials = new NetworkCredential("username", "password"); using (MailMessage mm = new MailMessage("from", "to", "subject", "body")) { using (Attachment attachment = new Attachment("myfile")) { mm.Attachments.Add(attachment); mm.BodyEncoding = System.Text.Encoding.UTF8; mm.DeliveryNotificationOptions = DeliveryNotificationOptions.OnFailure; string userState = "anything"; ss.SendCompleted += new SendCompletedEventHandler(SendCompletedCallback); ss.SendAsync(mm, userState); } } }; [/CODE]
"Using" is pointless here. [code] SmtpClient ss = new SmtpClient("smtp.gmail.com", 587); ss.EnableSsl = true; ss.Timeout = 10000; ss.DeliveryMethod = SmtpDeliveryMethod.Network; ss.UseDefaultCredentials = false; ss.Credentials = new NetworkCredential("username", "password"); MailMessage mm = new MailMessage("from", "to", "subject", "body"); Attachment attachment = new Attachment("myfile"); mm.Attachments.Add(attachment); mm.BodyEncoding = System.Text.Encoding.UTF8; mm.DeliveryNotificationOptions = DeliveryNotificationOptions.OnFailure; string userState = "anything"; ss.SendCompleted += new SendCompletedEventHandler(SendCompletedCallback); ss.SendAsync(mm, userState); [/code]
Are you using .NET 4 or 4.5? And your problem is, that you are disposing the SmtpClient before it is done sending.
[QUOTE=SiPlus;38445931]"Using" is pointless here. [code] SmtpClient ss = new SmtpClient("smtp.gmail.com", 587); ss.EnableSsl = true; ss.Timeout = 10000; ss.DeliveryMethod = SmtpDeliveryMethod.Network; ss.UseDefaultCredentials = false; ss.Credentials = new NetworkCredential("username", "password"); MailMessage mm = new MailMessage("from", "to", "subject", "body"); Attachment attachment = new Attachment("myfile"); mm.Attachments.Add(attachment); mm.BodyEncoding = System.Text.Encoding.UTF8; mm.DeliveryNotificationOptions = DeliveryNotificationOptions.OnFailure; string userState = "anything"; ss.SendCompleted += new SendCompletedEventHandler(SendCompletedCallback); ss.SendAsync(mm, userState); [/code][/QUOTE] I'm amazed that you've taken the exact same code and made it unreadable.
.Net 4.5, I'll see about removing the using statement around the smtpclient [editline]14th November 2012[/editline] All right, - I removed the using statement around smtp client - If I send normally and not asynchronous, it sends perfectly with attachment (although hangs the program up) ss.send(mm); - try-catch statements don't show me anything - Everything goes properly, the callback is called. - removed mm.DeliveryNotificationOptions = DeliveryNotificationOptions.OnFailure; Gmail won't send a receipt
In your using statement the object is only available as soon you are inside the scope, now that its asynchronous it will no longer exit and has eventually not finished the work yet. Edit: The best would be to declare it as a member in one of your classes to ensure its always available.
The whole email sending is set up in a static member : [CODE]public static void sendEmail()[/CODE] when new SmtpClient isn't in a using statement I get [CODE]A first chance exception of type 'System.ObjectDisposedException' occurred in System.dll[/CODE] So I use .Dispose() (tried multiple places) and it gets rid of the error but still does not send
You need to dispose the client, message and attachment in a callback, otherwise .Dispose() runs before the email is sent. If SendAsync returns a Task you should be able to await that in the using statement. That way the objects are automatically disposed once the email is sent. [editline]14th November 2012[/editline] The ObjectDisposedException probably happens because the GC collects the client before SendAsync executes. If you use await that will keep a reference until after the using statements are closed, otherwise you could have a collection of clients somewhere that are disposed and removed from a callback.
[QUOTE=Jookia;38446620]I'm amazed that you've taken the exact same code and made it unreadable.[/QUOTE] Making code unreadable increases performance and the greatest delay when sending an email is obviously processing the code to send the SMTP packets and not the email sending itself!!
I got around it (I believe) [CODE]ss.SendCompleted += (s, e) => { ss.Dispose(); mm.Dispose(); };[/CODE] Also, noob mistakes as I'm not a C# programmer. I've learned that file access needs to be handled carefully. Thanks everyone (for now)
[QUOTE=SiPlus;38445931]"Using" is pointless here. [code] SmtpClient ss = new SmtpClient("smtp.gmail.com", 587); ss.EnableSsl = true; ss.Timeout = 10000; ss.DeliveryMethod = SmtpDeliveryMethod.Network; ss.UseDefaultCredentials = false; ss.Credentials = new NetworkCredential("username", "password"); MailMessage mm = new MailMessage("from", "to", "subject", "body"); Attachment attachment = new Attachment("myfile"); mm.Attachments.Add(attachment); mm.BodyEncoding = System.Text.Encoding.UTF8; mm.DeliveryNotificationOptions = DeliveryNotificationOptions.OnFailure; string userState = "anything"; ss.SendCompleted += new SendCompletedEventHandler(SendCompletedCallback); ss.SendAsync(mm, userState); [/code][/QUOTE] You forgot to call ss.Dispose(). That's the whole point of using...
Isn't wrapping in a using statement supposed to dispose once it is one done automatically?
More about...[URL="http://net-informations.com/q/faq/default.html"]C# Using Statement[/URL] Eldo [QUOTE=wutanggrenad;38459126]Isn't wrapping in a using statement supposed to dispose once it is one done automatically?[/QUOTE] [highlight](User was permabanned for this post ("bot" - postal))[/highlight]
[QUOTE=wutanggrenad;38459126]Isn't wrapping in a using statement supposed to dispose once it is one done automatically?[/QUOTE] More or less, but it will be disposed [U]at the end of the [I]using[/I] statement[/U] and not "when it's done". All [I]using[/I] is is a shorthand for [code]var resource = ... try { ... } finally { resource.Dispose(); }[/code], which is very useful through being a safe way to do these things. It also behaves correctly in conjunction with Async. Of course if you have asynchronous code that needs the resource you have to either [I]await[/I] it or call [I].Dispose()[/I] differently. The latter is actually not always [I]strictly[/I] necessary, but it's still good form and the safer way to program. (Most IDEs should give you a warning for not disposing of stuff.) (Looks like this thread was bumped by advertising spam or something like that. I take that as opportunity to answer that last question and also hopefully ensure it's being marked as read again for everyone since I know there's an FP bug that prevents this in some cases.)
Sorry, you need to Log In to post a reply to this thread.