SmtpClient get result from server on send - c#

The SmtpClient send method returns void. Is there any way to get the server response? Do I just assume it was successful unless it throws an exception?
The class I'm referring to... http://msdn.microsoft.com/en-us/library/system.net.mail.smtpclient.aspx

To answer your second point, yes, all you can do is assume it's successful - meaning it got the message to the server and the server accepted it, unless you get an exception.
You probably already know the rest of this, but just in case...
From there, the email could get lost and not delivered any number of ways. Your server may accept it and decide not to send it, or accept it and lose power before crashing. It may get blocked by a spam filter along the way, etc.
You can think of an email as being similar to a regular piece of mail in that it passes through several hands between the sender and the recipient. From your code, you can only confirm that it got to the SMTP server you're using to send, which is similar to handing it to a teller at the post office. You don't know (or need to know) how the message is routed from there. it could be by air, ground, or carrier pigeon. You're out of the equation - you don't need to know how it gets sent, just that you trust that they know how to send it. (The same can be said for an email.)
If you need to confirm that the recipient opened it, there are ways of embedding an image in an HTML message on your server and tracking in your logs when that image is accessed, etc. (Google email tracking and email open tracking)
On the other hand...
If the server rejects it, then you do get a server response in a manner of speaking - there should be an error code and a description in the error, which you can use to troubleshoot why it didn't make it, or use error handling to try another route, etc.

You can utilize SendCompleted Event to check that your smtpclient works fine like this:
http://msdn.microsoft.com/en-us/library/system.net.mail.smtpclient.sendcompleted.aspx
But you cannot get confirmation that your message reached recipient because it may stuck in any server/filter in message chain.

You assume that it was successful unless it throws... although success in this case only means that it was accepted by the mail server, anything else is then up to the server...
IF you want a little bit of control you can use SendAsync and hook the SendCompleted event...

Related

Reload IMAP-Message

I have created an IMAP-Server. Now I am searching a way to force the client (in my case an iPhone) to reload a message, because it has changed on the server-side. Does somebody know a way to do this?
The body of a message is not allowed to change in IMAP; the only data item that may be changed for an existing message is the list of flags.
If you want to mimic a change in message body, you effectively have to tell your client that the original message was removed, and a new one created. You achieve the former by sending an EXPUNGE response with the message’s original sequence number, and the latter by sending an EXISTS and/or RECENT response, after which the client would typically issue a FETCH command for the new message.
The IMAP server can't force the IMAP client to do anything.
The closest thing to what you're looking for is IMAP IDLE. With IMAP IDLE, the server can push certain notifications to the client (if the client asked to receive them). The client can then do whatever it wants when it gets those notifications.

Throwing Exception while sending Email to multiple recipients using smtp client

I have an application which uses SmtpClient to send an email. I am trying to send an email to multiple recipients. I have two recipients in my to list e.g "aman#gmail.com,abc#xyz.com". and I am trying to send the email to this list but my application is throwing the exception as below:
Client does not have permission to submit mail to this server. The server response was: 4.7.1 (abc#xyz.com): Relay access denied.
because of this aman#gmail.com is also not able to receive the email.
I need to implement the functionality that even there is an invalid address like abc#xyz.com in the ToList, an email should be sent successfully to aman#gmail.com.
Can anybody please help me in this?
Does this error message come from your own email server, or from that of xyz.com? I'm guessing it's your own server, and that you either need to aunthenticate before sending, or use your own email address for sending (but the latter is kind of a long shot -- "we do not relay" means a server which is neither the sender's or the recipient's refuses to act as a middleman). It is also possible that the mail exchanger for xyz.com is misconfigured (either the MX record in DNS points to the wrong server, or the admin failed to configure it to accept this responsibility - technically basically the same thing) or that your client somehow ends up connecting to the wrong place.
(Not a proper answer but this got too long to fit in a comment.)

Checking if a Mail Server uses SSL without trying to send an e-Mail

I'm using C#, and while working on a sending mail routine using the tools available on the .NET Framework and I've sumbled upon two situations
One mail server that requires SSL
One mail server that doesn't support SSL
So when using a generic mail sending tool, I've noticed that I should ask the user if SSL should be used, or figure it by coding.
When I try to send an E-Mail not using SSL through a mail server that requires it, I get an exception.
When I try to send an E-Mail using SSL through a mail server that doesnt support it, I get an exception.
By doing this, it should be easy to check wether I should use it or not.
But I want a smarter way to do this. I didn't find any way to do so. Is there one ?
Personally, I do not believe that your code should be "Automagically" determining if SSL should be used.
When the e-mail service is configured by the users, they should be telling you how it works and what is needed.
You can see this behavior by the way the out of the box .NET SMTP which you must tell it how it is.
To further this, some services have a different URL for SSL and non SSL, and maybe users SHOULD be using SSL, but you could let them accidentally send the wrong way.
bool supportsSSL = true;
Stream stream = new SslStream(client.GetStream(), false);
try
{
((SslStream)stream).AuthenticateAsClient("pop3.xyz.com");
}
catch (Exception e)
{
supportsSSL =false;
}
It sounds like you have the answer. As long as the SMTP library you are using does the right thing when throwing the exception, try ssl first, then fallback to non-ssl, and handle that error case (i.e. total failure) if it happens.
I think you are concerned because you don't know what's going on under the covers when the exception is thrown, and if that's so, I feel the same. I don't know if your .net toolkit provides the facilities, but you should be able to make the connection with a lower-level type connection object which allows you to test whether or not it's possible to make an ssl connection and check the return value of your attempt, then decide how to proceed based on that.
It may be more trouble than it's worth though, because you might then need to bolt on SMTP functionality to your new connection type, if your SMTP library doesn't support using an already established connection. Which is the long way around saying, you're probably doing well enough with catching the exception and trying again.
In reference to #Mitchel's answer, I'd say it's perfectly okay if it's automagic as long as the right notification is made, and of course the context is right. SMTP is still pretty often plain text, so any expectation of encryption for email is pretty low. Login credentials are another matter. If this is an app an end user would use, you certainly ought to make sure they're connecting over SSL if credentials will be exchanged.

The CDO message is not sent and the message's attached file is not free to delete

I am trying to send a message with attachment using CDO object. When the SMTP Server is available and all the information is correct, the message is correctly sent with the attachment.
However, if the SMTP Server is incorrect the message is not sent (as expected), but it seems to be "stuck" somewhere. I am using:
Fields["http://schemas.microsoft.com/cdo/configuration/sendusing"] = 2
I've searched over the Internet, and found that this option would give a 60 second timeout. But the file I attached to the message is never available.
The test that I've done is to send a message with an attached file and using an invalid SMTP Server. Then, I wait for a few minutes and try to delete the file I had attached. However, when I try do it, I have a permission problem. When I kill the sending email program, I am able to delete the file.
I want to know how to configure the timeout to make sure it gives up sending the message, how I "detach" the file when the message is not sent and how to make the program wait for the message to be sent (I want to send the message and then erase the attached file from the computer. So I need to know when the message was really sent or when it was timedout).
CDO is hopelessly obsolete, you really need to consider switching to System.Net.Mail. The specific problem sounds like a file locking issue. Quacks like a bug in CDO, it would open the attachment to compose the email message but forgets to close the file when the SMTP server balks.
This bug is probably exacerbated by the way .NET deals with COM servers, like CDO. The COM object doesn't get released until the garbage collector runs. Which can take a while, especially when your program doesn't do anything significant after trying to send the email. A workaround for that is calling Marshal.ReleaseComObject() on the CDO object. Tends to not work when you have other CDO interface references in your program, those references tend to be hidden. GC.Collect() + GC.WaitForPendingFinalizers() is the big hammer, after you nulled any object reference.
But, really, use System.Net.Mail.

POP3 Transmission Process

I was wondering if anyone could help me out (not with code, although that would be appreciated), with the logic behind checking and retrieving messages from a POP3 mail server.
I.e.
Establish connection
Validate credentials
Enumerate message list
Check each message to see if it's "new"
Download "new" message(s).
Would this be the correct way about doing this?
Thank you
The best way of looking at something like this is to have a look what something else does. Run Wireshark or some other packet capture software, and use an e-mail client to check. Anyway, the basics of a POP3 session are as follows:
USER username
PASS password
LIST <-- Shows the size of each waiting message
UIDL <-- Shows a unique ID for each waiting message
RETR 1 <-- Retrieves message with index 1
DELE 1 <-- Deletes the message you just retrieved
QUIT
The first char of all of the responses except RETR will be a + (success) or a - (failure).
If you are deleting messages off the server after retrieving them, you don't need to bother with UIDL. If you are leaving them, you can use UIDL to get a unique ID for each message which you store locally to show you have retrieved that message before.
For more details, see the RFC. Wikipedia also lists a more in depth example, showing the server response.
These should be useful:
POP3 Email Client (.NET 2.0)
POP3 Client as a C# Class
Retrieve Mail From a POP3 Server Using C#
POP3 Sequence Diagram
POP3 Reference

Categories