Wysyłanie wiadomości elektronicznych. Aplikacja KlientSmtp dr Zbigniew Lipiński Instytut Matematyki i Informatyki UO ul. Oleska 48, 50-204 Opole zlipinski@math.uni.opole.pl
Protokół SMTP, Simple Mail Transfer Protocol RFC 2821, J. Klensin, Simple Mail Transfer Protocol, April 2001, Obsoleted-By RFC 5321, Updated-By RFC 5336 RFC 2645, R. Gellens, On-demand mail relay (ODMR) SMTP with Dynamic IP Addresses, August 1999, PROPOSED STD. RFC 5321, J. Klensin, Simple Mail Transfer Protocol, October 2008, Updates RFC 1123, Status: DRAFT STD, SMTP jest protokołem transportowym serwera pocztowego. Protokół SMTP służy do: trasowania, replikacji widomości między serwerami SMTP, przesyłania widomości email od klienta SMTP do serwera SMTP. Protokół SMTP wykorzystuje w warstwie transportowej modelu OSI protokół TCP, port 25. Format adresu pocztowego SMTP: nazwauzytkownika@nazwadnsowadomeny Przykład. st001@student.math.uni.opole.pl 2
Sesja SMTP wysłania wiadomości elektronicznej Proces wymiany wiadomości SMTP: Host buduje połączenie (TCP) z serwerem. Wymienianie są 3 wiadomości: host -(1)-> serwer -(2)-> host -(3)-> serwer. Serwer SMTP potwierdza otwarcie sesji. Serwer wysyła wiadomość z kodem 220 (opening message). Klient SMTP wysyła wiadomość służąca do identyfikacji hosta. Wiadomość z komendą EHLO. Klient SMTP wysyła wiadomość z komendą MAIL służąca do identyfikacji nadawcy. Serwer potwierdza gotowość do odebrania maila. Serwer odpowiada wiadomością zawierająca komendę: 250 OK Klient SMTP wysyła wiadomość z informacją o odbiorcy maila (RCPT TO). Serwer akceptuje dane odpowiadając komendą: 250 OK. Klient SMTP wysyła wiadomość z komendą DATA <CRLF> informując o początku przesyłania danych maila. Serwer akceptuje komendę, odpowiadając komendą: 354. Klient wysyła dane. Znakiem końca transmisji danych maila jest '.'. Serwer akceptuje komendę końca danych wysyłając wiadomość z komenda: 250 OK. Klient kończy sesje wysyła wiadomość z komendą QUIT. Serwer potwierdza koniec sesji wysyłając wiadomość z kodem: 221. 3
Przykład: sesja SMTP Przykład sesji SMTP: Wiadomość jest wysyłana przez Smith'a z hosta nadawca.com do Jones'a z hosta odbiorca.com. Smith, Jones to nazwy skrzynek. S: 220 odbiorca.com (serwer potwierdza otwarcie sesji) K: EHLO nadawca.com (klient wysyła wiadomość służąca do identyfikacji hosta) S: 250-odbiorca.com greets nadawca.com S: 250-8BITMIME S: 250-SIZE S: 250-DSN (250-delivery status notification) S: 250 HELP K: MAIL FROM:<Smith@nadawca.com> S: 250 OK K: RCPT TO:<Jones@odbiorca.com> S: 250 OK K: DATA S: 354 Poczatek danych maila <CRLF>.<CRLF> K: dane maila. K: dane maila. K:. S: 250 OK K: QUIT S: 221 odbiorca.com 4
Procedury SMTP Procedury SMTP: 1. Session Initiation (rozpoczęcie sesji). 2. Mail Transaction (wysłanie maila). 3. Forwarding Mail (przesłanie maila). 4. Verifying Mailbox Names (sprawdzenie nazw skrzynek, rozwinięcie listy adresowej). 5. Sending to Terminals (wysłanie maila). 6. Opening and Closing Exchanges (otwarcie i zamknięcie wymiany wiadomości). 5
Procedury SMTP Procedura SMTP: Session Initiation. Sesja między klientem a serwerem SMTP jest otwarta gdy: host nawiązuje połączenie TCP z serwerem (budowa sesji TCP), serwer odpowiada wiadomością potwierdzającą otwarcie sesji, wiadomości z kodem 220. Serwer SMTP może nie zaakceptować próby rozpoczęcia sesji przez klienta SMTP wysyłając wiadomość z kodem 554 (zamiast kodu 220). Po rozpoczęciu sesji klient SMTP wysyła informacje identyfikujące hosta - wiadomość HELO, EHLO. 6
Procedury SMTP Procedura SMTP: Mail Transactions. Procedura Mail Transaction składa sie trzech kroków: identyfikacja skrzynki nadawcy poleceniem MAIL Struktura komendy: MAIL FROM:<reverse-path> [SP <parametry maila> ] <CRLF> Zmienna reverse-path oznacza adres skrzynki nadawcy (używany do wysyłania komunikatów o błędzie). ciąg komend RCPT, (skrót od RECIPIENT), przekazujących informacje do odbiorcy. Struktura komendy: RCPT TO:<forward-path> [ SP <rcpt-parameters> ] <CRLF> Zmienna forward-path oznacza adres odbiorcy maila. komenda DATA zwraca dane maila. Struktura komendy: DATA <CRLF>. Wskaźnik końca maila '.' służy do potwierdzenia transakcji. Potwierdzenie poprawności odbioru następuje przez wysłanie odpowiedzi: '250 OK'. Opowiedź: '550 Failure', oznacza, ze odbiorca jest nieznany. Przykład: Struktura komend MAIL, RCPT, DATA. MAIL FROM:<reverse-path> [SP <mail-parameters> ] <CRLF> RCPT TO:<forward-path> [ SP <rcpt-parameters> ] <CRLF> DATA <CRLF> Przykład: Komenda 503 Jeżeli komenda RCPT nie będzie poprzedzona komenda MAIL to serwer zwraca wiadomość z kodem 503 'Bad sequence of commands'. 7
Procedury SMTP Przykład: Procedura Mail Transaction. Wysłanie maila ze skrzynki Smith do 3 skrzynek Jones, Green, Brown. Nadawca: MAIL FROM:<Smith@Alpha.ARPA> Odbiorca: 250 OK Nadawca: RCPT TO:<Jones@Beta.ARPA> Odbiorca: 250 OK Nadawca: RCPT TO:<Green@Beta.ARPA> Odbiorca: 550 No such user here Nadawca: RCPT TO:<Brown@Beta.ARPA> Odbiorca: 250 OK Nadawca: DATA Odbiorca: 354 Start mail input; end with <CRLF>.<CRLF> Nadawca: tresc maila... Nadawca:...tresc maila. Nadawca:. Odbiorca: 250 OK Nadawca - klient SMTP. Odbiorca - serwer SMTP. 8
Procedury SMTP Procedura SMTP: Forwarding Mail. Procedura 'Forwarding Mail' służy przesyłania maila przez serwer SMTP do innego serwera SMTP. Typy przesyłania maili: Silent forwarding, przesyłanie maila bez informowania klienta SMTP. Przesłanie maila z poinformowaniem klienta SMTP (kod 251). Przykład: Nadawca: RCPT TO:<Postel@USC-ISI.ARPA> Odbiorca: 251 User not local; will forward to <Postel@USC-ISIF.ARPA> Przykład: Nadawca: RCPT TO:<Paul@USC-ISIB.ARPA> Odbiorca: 551 User not local; please try <Mockapetris@USC-ISIF.ARPA> 9
Procedura SMTP: Verifying Mailbox Names Procedura SMTP Verifying Mailbox Names. Sprawdzenie nazw skrzynek (nazw użytkowników), rozwinięcie listy adresowej. Procedura wykonywana jest poprzez wywołanie komend VRFY i EXPN. Komenda VRFY służy do identyfikacji nazwy użytkownika. Format odpowiedzi na komendę VRFY: User Name <local-part@domain> local-part@domain Komenda EXPN służy do uzyskania listy adresowej (listy mailingowej). Przykład: Komenda VRFY, odpowiedź serwera kodem 250. S: VRFY Smith R: 250 Fred Smith <Smith@USC-ISIF.ARPA> Przykład: Komenda VRFY, odpowiedź serwera kodem 251. S: VRFY Smith R: 251 User not local; will forward to <Smith@USC-ISIQ.ARPA> 10
Procedura SMTP: Opening and Closing Exchanges Procedura SMTP: otwarcie i zamknięcie wymiany. Komenda otwarcia wymiany wiadomości: ehlo = "EHLO" SP Domain CRLF helo = "HELO" SP Domain CRLF Komenda zamknięcia wymiany wiadomości: QUIT <CRLF> Przykład: Otwarcie wymiany. Odbiorca: 220 BBN-UNIX.ARPA Simple Mail Transfer Service Ready Nadawca: HELO USC-ISIF.ARPA Odbiorca: 250 BBN-UNIX.ARPA Przykład: Zamknięcia procesu wymiany. Nadawca: QUIT Odbiorca: 221 BBN-UNIX.ARPA Service closing transmission channel 11
Komendy SMTP Lista komend SMTP: EHLO lub HELO MAIL RCPT (recipient) DATA RSET (reset) VRFY (verify) EXPN (expand) HELP (help) NOOP (no option) QUIT RESET (RSET) HELP NOOP Komenda oznacza, że wszystkie wiadomości SMTP związane z przesłaniem maila są usunięte z serwera SMTP. Komendę RSET może wysłać odbiorca i nadawca mail. Składnia: "RSET" CRLF Komenda wysyłana przez klienta SMTP. Serwer SMTP zwraca informacje o pomocy do klienta. Składnia: "HELP" [ SP String ] CRLF Komenda wymusza odpowiedź serwera 'OK'. Składnia: "NOOP" [ SP String ] CRLF 12
Usługa identyfkacji hostów SMTP RFC 2554, J. Myers, SMTP Service Extension for Authentication, March 1999. Składnia polecenia AUTH: AUTH mechanizm [wstępna odpowiedź] Argumenty polecenia: string identyfikujący typ mechnizmu SASL (Simple Authentication and Security Layer) uwierzytelnienia i bezpieczeństwa serwera, opcjonalnie, klient wysyła string, zapisany w schemacie kodowania danych binarnych BASE64. Ograniczenia stosowania komendy AUTH: komendę AUTH zakończoną uwierzytelnieniem, można użyć tylko raz w danej sesji SMTP. Po pozytywnym uwierzytelnieniu, na kolejną komendę AUTH serwer odpowiada kodem błędu 503. polecenia AUTH nie można stosować podczas procedury mail transaction. 13
Usługa identyfkacji hostów SMTP Do komendy MAIL FROM dodano opcjonalny parametr używający słowa kluczowego AUTH. Rozszerzono do 500 maksymalną liczbę znaków w komendzie MAIL FROM. Jeżeli serwer SMTP nie obsługuje komendy AUTH zwraca wiadomość z kodem 504. Po komendzie klienta AUTH, serwer przesyła wiadomość z kodem 334 i string kodowany w schemacie BASE64. Klient odpowiada stringiem kodowanym w schemacie BASE64. Przykład: S: 220 smtp.uni.opole.pl ESMTP server ready C: EHLO student.uni.opole.pl S: 250-smtp.uni.opole.pl S: 250 AUTH CRAM-MD5 DIGEST-MD5 C: AUTH STUDENT S: 504 Unrecognized authentication type. C: AUTH CRAM-MD5 S: 334 PENCeUxFREJoU0NnbmhNWitOMjNGNndAZWx3b29kLmlubm9zb2Z0LmNvbT4= C: ZnJlZCA5ZTk1YWVlMDljNDBhZjJiODRhMGMyYjNiYmFlNzg2ZQ== S: 235 Authentication successful. 14
Standard MIME MIME, (ang.) Multipurpose Internet Mail Extensions. RFC 1521, 1522, 2045, 2046, 2047, 2048. MIME rozszerza funkcji protokołu SMTP, pozwalający na wysyłanie binarnych załączników (załączniki nie w kodzie ASCII). MIME określa algorytm kodowania znaków nie mających kodów standardzie w US-ASCII. MIME określa standardy umożliwiające: przesłanie treści wiadomości w formacie innym niż US-ASCII, rozszerzenie do nietekstowych formatów treści wiadomości (extensible set of different formats for non-textual message bodies), wieloczęściowe wiadomość (multi-part message bodies), przesłanie nagłówka wiadomości w formacie innym niż US-ASCII. 15
Klient SMTP.Net System.Net.Mail Namespace Public classes (wybór) AlternateView Attachment AttachmentCollection MailAddress MailMessage SmtpClient // Represents the format to view an email message. //Represents an attachment to an e-mail. //Stores attachments to be sent as part of an e-mail message. //Represents the address of an electronic mail sender or recipient. //Represents an e-mail message that can be sent using the SmtpClient class. //Allows applications to send e-mail by using the Simple Mail Transfer Protocol (SMTP). SmtpException //Represents the exception that is thrown when the SmtpClient is not able to complete a Send or SendAsync operation. 16
Klient SMTP.Net SmtpClient Class public class SmtpClient : IDisposable Constructors SmtpClient() // Initializes a new instance of the SmtpClient class by using configuration file settings. SmtpClient(String) // Initializes a new instance of the SmtpClient class that sends e-mail by using the specified SMTP server. SmtpClient(String, Int32) // Initializes new instance of SmtpClient class that sends e-mail by using the specified SMTP server and port. SmtpClient(String^ host, int port) 17
Klient SMTP.Net SmtpClient Class Public methods Dispose() //Sends a QUIT message to the SMTP server, gracefully ends the TCP connection, and releases all resources used by the // current instance of the SmtpClient class. Protected methods OnSendCompleted //Raises the SendCompleted event. Public methods (wybór) Send(MailMessage) Send(String, String, String, String) //Sends the specified message to an SMTP server for delivery. //Sends the specified e-mail message to an SMTP server for delivery. //The message sender, recipients, subject, and message body are specified using String objects. SendAsync(MailMessage, Object) //Sends the specified e-mail message to an SMTP server for delivery. This method does not block // the calling thread and allows the caller to pass an object to the method that is //invoked when the operation completes. SendAsync(String, String, String, String, Object) //Sends an e-mail message to an SMTP server for delivery. The message sender, // recipients, subject, and message body are specified using String objects. This //method does not block the calling thread // and allows the caller to pass an object to the method that is invoked when the operation completes. ToString //Returns a string that represents the current object. 18
SmtpClient Class Public property ClientCertificates Credentials DeliveryMethod EnableSsl Host Port ServicePoint TargetName Timeout //Specify which certificates should be used to establish the SSL connection. //Gets or sets the credentials used to authenticate the sender. //Specifies how outgoing email messages will be handled. //Specify whether the SmtpClient uses SSL to encrypt the connection. //Gets or sets the name or IP address of the host used for SMTP transactions. //Gets or sets the port used for SMTP transactions. //Gets the network connection used to transmit the e-mail message. //Gets or sets the Service Provider Name (SPN) to use for authentication when using extended protection. //Gets or sets a value that specifies the amount of time after which a synchronous Send call times out. Public event SendCompleted //Occurs when an asynchronous e-mail send operation completes. 19
Przykład użycia klas MailAddress, MailMessage. public static void CreateCopyMessage(string server) MailAddress from = new MailAddress("ben@contoso.com", "Ben Miller"); MailAddress to = new MailAddress("jane@contoso.com", "Jane Clayton"); MailMessage message = new MailMessage(from, to); // message.subject = "Using the SmtpClient class."; message.subject = "Using the SmtpClient class."; message.body = @"Using this feature, you can send an e-mail message very easily."; // Add a carbon copy recipient. MailAddress copy = new MailAddress("Notification_List@contoso.com"); message.cc.add(copy); SmtpClient client = new SmtpClient(server); // Include credentials if the server requires them. client.credentials = CredentialCache.DefaultNetworkCredentials; Console.WriteLine("Sending an e-mail to 0 by using the SMTP host 1.", to.address, client.host); try client.send(message); catch (Exception ex) Console.WriteLine("Exception caught in CreateCopyMessage(): 0", ex.tostring() ); 20
Przykład użycia klasy Attachment. public static void CreateMessageWithAttachment(string server) // Specify the file to be attached and sent. // This example assumes that a file named Data.xls exists in the // current working directory. string file = "data.xls"; // Create a message and set up the recipients. MailMessage message = new MailMessage( "jane@contoso.com", "ben@contoso.com", "Quarterly data report.", "See the attached spreadsheet."); // Create the file attachment for this e-mail message. Attachment data = new Attachment(file, MediaTypeNames.Application.Octet); // Add time stamp information for the file. ContentDisposition disposition = data.contentdisposition; disposition.creationdate = System.IO.File.GetCreationTime(file); disposition.modificationdate = System.IO.File.GetLastWriteTime(file); disposition.readdate = System.IO.File.GetLastAccessTime(file); // Add the file attachment to this e-mail message. message.attachments.add(data); //Send the message. SmtpClient client = new SmtpClient(server); // Add credentials if the SMTP server requires them. client.credentials = CredentialCache.DefaultNetworkCredentials; try client.send(message); catch (Exception ex) Console.WriteLine("Exception in CreateMessageWithAttachment(): 0", ex.tostring()); 21
Przykład użycia klasy Attachment. // Display the values in the ContentDisposition for the attachment. ContentDisposition cd = data.contentdisposition; Console.WriteLine("Content disposition"); Console.WriteLine(cd.ToString()); Console.WriteLine("File 0", cd.filename); Console.WriteLine("Size 0", cd.size); Console.WriteLine("Creation 0", cd.creationdate); Console.WriteLine("Modification 0", cd.modificationdate); Console.WriteLine("Read 0", cd.readdate); Console.WriteLine("Inline 0", cd.inline); Console.WriteLine("Parameters: 0", cd.parameters.count); foreach (DictionaryEntry d in cd.parameters) Console.WriteLine("0 = 1", d.key, d.value); data.dispose(); 22
Przykład Klient SMTP. Źródło. http://msdn.microsoft.com/en-us/library/vstudio/system.net.mail.smtpclient(v=vs.100).aspx?cs-save-lang=1&cs-lang=cpp#code-snippet-2 using System; using System.Net; using System.Net.Mail; using System.Net.Mime; using System.Threading; using System.ComponentModel; namespace Examples.SmptExamples.Async public class SimpleAsynchronousExample static bool mailsent = false; private static void SendCompletedCallback(object sender, AsyncCompletedEventArgs e) // Get the unique identifier for this asynchronous operation. String token = (string) e.userstate; if (e.cancelled) Console.WriteLine("[0] Send canceled.", token); if (e.error!= null) Console.WriteLine("[0] 1", token, e.error.tostring()); else Console.WriteLine("Message sent."); mailsent = true; 23
public static void Main(string[] args) // Command line argument must the the SMTP host. SmtpClient client = new SmtpClient(args[0]); // Specify the e-mail sender. // Create a mailing address that includes a UTF8 character in the display name. MailAddress from = new MailAddress("jane@contoso.com", "Jane " + (char)0xd8+ " Clayton", System.Text.Encoding.UTF8); // Set destinations for the e-mail message. MailAddress to = new MailAddress("ben@contoso.com"); // Specify the message content. MailMessage message = new MailMessage(from, to); message.body = "This is a test e-mail message sent by an application. "; // Include some non-ascii characters in body and subject. string somearrows = new string(new char[] '\u2190', '\u2191', '\u2192', '\u2193'); message.body += Environment.NewLine + somearrows; message.bodyencoding = System.Text.Encoding.UTF8; message.subject = "test message 1" + somearrows; message.subjectencoding = System.Text.Encoding.UTF8; // Set the method that is called back when the send operation ends. client.sendcompleted += new SendCompletedEventHandler(SendCompletedCallback); // The userstate can be any object that allows your callback // method to identify this send operation. // For this example, the usertoken is a string constant. string userstate = "test message1"; client.sendasync(message, userstate); Console.WriteLine("Sending message, press c to cancel.press any other key to exit."); string answer = Console.ReadLine(); // If the user canceled the send, and mail hasn't been sent yet, // then cancel the pending operation. if (answer.startswith("c") && mailsent == false) client.sendasynccancel(); // Clean up. message.dispose(); Console.WriteLine("Goodbye."); 24
Przykład Klient SMTP. using System; using System.Net.Mail; namespace Microsoft.Samples.Mailer // Mailer sends an e-mail. It will authenticate using Windows authentication if the server requests it. static class Mailer enum MailMessagePart From, To, Subject, Message static void Main(string[] args) if (args.length < 4) Console.WriteLine( "Expected: mailer.exe [from] [to] [subject] [message]"); return; // Set mailservername to be the name of the mail server you wish to use to deliver this message string mailservername = "smtphost"; string from = args[(int) MailMessagePart.From]; string to = args[(int) MailMessagePart.To]; string subject = args[(int) MailMessagePart.Subject]; string body = args[(int) MailMessagePart.Message]; try // MailMessage is used to represent the e-mail being sent using (MailMessage message = new MailMessage(from, to, subject, body)) // SmtpClient is used to send the e-mail SmtpClient mailclient = new SmtpClient(mailServerName); // UseDefaultCredentials tells the mail client to use the Windows credentials of the account being used mailclient.usedefaultcredentials = true; // Send delivers the message to the mail server mailclient.send(message); Console.WriteLine("Message sent."); catch (FormatException ex) Console.WriteLine(ex.Message); catch (SmtpException ex) Console.WriteLine(ex.Message); 25
26