Saturday, February 04, 2006

שלום לכולם,

בעתיד הקרוב אני ניגש למבחן העדכון של MCSD ל-MCPD ואחד מהנושאים שם זה שליחת דוא"ל דרך דוט נט. אז בואו ונדבר על System.Net.Mail.

System.Net.Mail הוא הגירסה בדוט נט 2.0 של System.Web.Mail. כן כן, שמתם לב להבדל - העבירו את זה Namespace משני.

 

חלק א': שרת ה-SMTP ב-IIS (או: "The little email who could")

בואו נתחיל מהתחלה. בכל שרת אינטרנט של מיקרוסופט מותקן IIS שזה ה-Internet information services. שמתם לב שהדגשתי את ה-s ב-services? כן, ה-IIS המיקרוסופטי מכיל מספר שירותים אפשריים ולא רק את היכולת להגיש דפי אינטרנט. שלושת השירותים העיקריים שה-IIS מציע הם: הגשת דפי אינטרנט, גישת FTP ושרת SMTP. כולנו מכירים את יכולת הגשת דפי אינטרנט וכולנו פחות או יותר יודעים מה זה FTP ("נו, אתה יודע, זה כמו העתקת קבצים רגילה רק איטי ומתסכל"). אבל מה זה ה-SMTP הזה שהזכרתי?

בפשטות ובקצרה, שרת ה-SMTP המובנה ב-IIS הוא שירות מוכר, ידוע ואמין שמאפשר שליחת דוא"ל. במאמר זה אנחנו נלמד כיצד ניתן לנצל את השירות הזה דרך דוט נט בכדי לשלוח דוא"ל מתוך הישומיים שלנו.

בואו נביט ונראה שבאמת קיים כזה דבר. נפתח את IIS manager (פותחים Start --> Run --> Intermgr) ונביט מה אנחנו רואים שם:

כמו שאמרנו ה-IIS מציע לנו שלושה שרתים אפשריים: Web, Ftp, Smtp. בואו נביט על c:\inetpub

בתוך תיקיית ה-inetpub שהיא ברירת המחדל ל-IIS אפשר לראות שלושה תיקיות חשובות: wwwroot, ftproot, mailroot. את wwwroot כולנו מכירים מ-ASP.Net והיא הספרייה שבה אנו מפתחים ופורשים אפליקציות ASP.Net. כלומר, שם יושבים הקבצים בשביל השירות שדואג להגיש דפי אינטרנט. בצורה דומה, ה-ftproot היא הספרייה הראשית אליה ניגשים כאשר ניגשים לשירות ה-ftp של ה-IIS. לעומת הפשטות של ספריות ה-wwwroot וה-ftproot ספריית ה-mailroot קצת יותר מורכבת. בואו נביט עליה:

יש שלוש תיקיות עיקריות ב-mailroot:

  1. Pickup - כאשר פריט דואר נשלח לראשונה הוא מגיע לכאן ומחכה לניסיון הראשון לשלוח אותו.
  2. Queue - אם לאחר השליחה הראשונית יש צורך להמתין מאיזהשהי סיבה כאן ימתין הדוא"ל.
  3. Badmail - גן-עדן לדוא"ל שמשהו השתבש בצורה דרסטית בשליחה שלו.

מילה אחת אחרונה על התשתית של ה-IIS. בתוך הספריות השונות הדוא"ל יהיה עם סיומת eml ובעקרון מדובר בקובץ טקסט מפורמט (כמו שנראה בהמשך). ביחד איתו לרוב ימצא קובץ rtr שהוא היומן פעולות ("לוג") של חייו הקצרים אך המרתקים של הדוא"ל.

 

חלק ב': שליחת דוא"ל ראשון (או: "אם בהתחלה לא הצלחת כנראה שנכשלת")

בואו נראה קוד מאוד בסיסי לשליחת מייל

using System.Net.Mail;

MailMessage myMessage = new MailMessage("mail@JustinAngel.net","J@JustinAngel.net",
       "simple mail","hello justin, how are you today?");

SmtpClient mySmtp = new SmtpClient("127.0.0.1", 25);

mySmtp.Send(myMessage);

בקוד יצרנו MailMessgae חדשה שמקבלת כפרמטר ראשון את כתובת הדוא"ל של השולח, כפרמטר שני את כתובת הדוא"ל של מען ההודעה, נושא הדוא"ל ותוכן הדוא"ל. לאחר מכן פתחנו SmtpClient על המחשב הלוקאלי (פורט 25 הוא הפורט ברירת המחדל של ה-SMTP) ושלחנו דרכו את הדוא"ל.

מעכשיו ככה זה הולך לעבוד: MailMessage זה הדוא"ל שנשלח ו-SmtpClient שולח הודעות דוא"ל.

נריץ את הקוד ונקבל שגיאה:

Mailbox unavailable. The server response was: 5.7.1 Unable to relay for J@justinangel.net

הפתרון יחסית פשוט:

 Start --> Run --> intermgr --> right click smtp server --> Access --> Realy --> Add --> Ip Address: 127.0.0.1 --> Ok --> Apply

או קיי, טיפלנו בזה - בואו נריץ שוב.

הכל רץ חלק. ביינתים הדוא"ל שלנו הגיע לתיקיית inetpub\mailroot\Pickup ושרת ה-Smtp ניסה לשלוח אותו. ודרך הפיירוול במחשב חסמתי את פורט 25 ככה שביינתים השרת לא הצליח והדוא"ל עבר לתיקיית inetpub\wwwroot\Queue. נפתח את תיקיית ה-Queue:

נפתח את הקובץ הזה בפנקס רשימת וזה מה שנראה:

Received: from justin ([127.0.0.1]) by justin with Microsoft SMTPSVC(5.0.2172.1);
  Fri, 3 Feb 2006 19:31:57 +0200
mime-version: 1.0
from: J@justinAngel.net
to: mail@JustinAngel.net
date: 3 Feb 2006 19:31:57 +0200
subject: simple mail
content-type: text/plain; charset=us-ascii
content-transfer-encoding: quoted-printable
Return-Path: J@justinAngel.net
Message-ID: <JUSTINUFSXju17BKjJ000000001@justin>
X-OriginalArrivalTime: 03 Feb 2006 17:31:57.0344 (UTC) FILETIME=[BB696200:01C628E7]

hello justin, how are you today?

בקצרה, מדובר על פורמט MIME וזה הפורמט שדוא"ל עובר בעולם. אפשר לראות שנושא ההודעה שלנו שם, הכתובת מען שלנו שם, הכתובת משלוח המקורית שם ותוכן ההודעה שם. אז במקום שאנחנו נצטרך לדעת איך לעבוד עם הפורמט הזה מה שלמעשה קרה זה ש-System.Net.Mail כתב אותו בהתאם למה שביקשנו ממנו.

בואו נשכתב את הקוד שכתבנו למעלה ובמקום לעבוד עם Constructors נעבוד עם מאפיינים (גם באנגלית: Properties).


MailMessage
myMessage = new MailMessage();
myMessage.To.Add("J@justinAngel.net");
myMessage.From =  "mail@JustinAngel.net"; // will cause compliation error
myMessage.Subject = "simple mail";
myMessage.Body = "hello justin, how are you today?";

SmtpClient mySmtp = new SmtpClient();
mySmtp.Host =
"127.0.0.1";
mySmtp.Port = 25;

mySmtp.Send(myMessage);

חלק ג': חוקרים את MailMessage (או: "4,000 טריקים בתוך מאפיינים")

MailAdress - שכתוב הדוגמה

MailAddress היא מחלקה שיועדה להכיל כתובת דוא"ל ושם תצוגה כמשתנה אופציונלי נוסף. נשכתב את הדוגמה למעלה

  MailMessage myMessage = new MailMessage();

 

  myMessage.To.Add(new MailAddress("J@justinAngel.net", "Justin Angel"));

  myMessage.From = new MailAddress("mail@JustinAngel.net");

 

  myMessage.Subject = "simple mail";

  myMessage.Body = "hello justin, how are you today?";

 

  SmtpClient mySmtp = new SmtpClient();

  mySmtp.Host = "127.0.0.1";

  mySmtp.Port = 25;

 

  mySmtp.Send(myMessage);

כמען לדוא"ל יצרנו מחלקת MailAddress חדשה שתפנה לכתובת הדוא"ל שלי J@JustinAngel.Net ותציג בתצוגה את השם שלי Justin Angel. כשולח לדוא"ל יצרנו MailAddress נוסף אבל שיכיל כתובת דוא"ל בלבד בלי שם ותיאור.

MailMessage.Form הוא מסוג מחלקת MailAddress (ולכן הדוגמה האחרונה בחלק ב' לא תתקמפל).

אם הבטתם מקרוב שמתם לב למשהו מעניין MailMessage.To הוא לא ערך בודד כמו MailMessage.From אלא אוסף של MailAddress. כלומר, לדוא"ל יש אוסף של מענים ולא מען בודד. עוד אינפורמציה מעניינת (וטיפה לא קשורה) היא שמדובר באוסף שפנימית עובד עם Generics. עכשיו, אתם כנראה חושבים "היי, זה מתחיל להזכיר לי את האי-מיילים בעבודה! אבל לאי-מיילים בעבודה יש עוד המון תכונות למשל גם יש מעני CC ומעני BCC". אז נכון, יש MailMessage.To שאלו הם המענים הרגילים, יש את MailMessage.CC שאלו הם המענים המכותבים ויש את MailMessage.BCC שאלו הם המענים המכותבים הנסתרים.

  MailMessage myMessage = new MailMessage();

 

  myMessage.To.Add(new MailAddress("J@JustinAngel.net", "Justin Angel"));

  myMessage.To.Add(new MailAddress("Ayende@ayende.com", "Oren Eini"));

  myMessage.CC.Add(new MailAddress("oren.ellenbogen@hmail.com", "Oren Ellenbogen"));

  myMessage.CC.Add(new MailAddress("royo@oshrovo.com", "Roy Osherove"));

  myMessage.Bcc.Add(new MailAddress("mikiwatts@orb-software.com", "Miki Watts"));

 

  myMessage.From = new MailAddress("mail@JustinAngel.net");

 

  myMessage.Subject = "simple mail";

  myMessage.Body = "hello justin, how are you today?";

 

  SmtpClient mySmtp = new SmtpClient();

  mySmtp.Host = "127.0.0.1";

  mySmtp.Port = 25;

 

  mySmtp.Send(myMessage);

אז בדוגמה הזו שלחנו לאורן עיני ולי דוא"ל, כיתבנו את אורן אלנבוגן ואת רועי אושרוב ובאופן נסתר את מיקי ווטס (קישורים לבלוגים שלהם זמינים בצד). עבדנו עם המענים כאוסף לכל דבר. אגב, תמנעו בבקשה מלהריץ את הדוגמאות האלו עם הכתובות דוא"ל הספציפיות האלו.

אם אתם דומים לי אז אתם כנראה עכשיו אתם חושבים "או קיי, זה כמו אי-מייל בעבודה, אבל זה לא מייל אמיתי לפני שאני מסמן אותו כדחוף". אכן, ניתן לסמן MailMessage כדחופה בעזרת MailMessage.Priority.

 

  MailMessage myMessage = new MailMessage();

 

  myMessage.To.Add(new MailAddress("J@JustinAngel.net", "Justin Angel"));

  myMessage.To.Add(new MailAddress("Ayende@ayende.com", "Oren Eini"));

  myMessage.CC.Add(new MailAddress("oren.ellenbogen@hmail.com", "Oren Ellenbogen"));

  myMessage.CC.Add(new MailAddress("royo@oshrovo.com", "Roy Osherove"));

  myMessage.Bcc.Add(new MailAddress("mikiwatts@orb-software.com", "Miki Watts"));

 

  myMessage.From = new MailAddress("mail@JustinAngel.net");

            myMessage.Priority = MailPriority.High;

 

  myMessage.Subject = "simple mail";

  myMessage.Body = "hello justin, how are you today?";

 

  SmtpClient mySmtp = new SmtpClient();

  mySmtp.Host = "127.0.0.1";

  mySmtp.Port = 25;

 

  mySmtp.Send(myMessage);

משהו שמאוד נפוץ לעשות בשליחת דוא"ל אוטומטי זה ליצור שכתובת הדוא"ל של שולח ההודעה היא כתובת מיוחדת שמדגישה מהמען בבקשה לא הגיב. אז באמת אנחנו לא רוצים שאנשים יגיבו לכתובת ה-From אז נשים כתובת ReplyTo.

  MailMessage myMessage = new MailMessage();

 

  myMessage.To.Add(new MailAddress("J@JustinAngel.net", "Justin Angel"));

  myMessage.To.Add(new MailAddress("Ayende@ayende.com", "Oren Eini"));

  myMessage.CC.Add(new MailAddress("oren.ellenbogen@hmail.com", "Oren Ellenbogen"));

  myMessage.CC.Add(new MailAddress("royo@oshrovo.com", "Roy Osherove"));

  myMessage.Bcc.Add(new MailAddress("mikiwatts@orb-software.com", "Miki Watts"));

 

  myMessage.From = new MailAddress("mail@JustinAngel.net");

  myMessage.Priority = MailPriority.High;

            myMessage.ReplyTo = new MailAddress("do-not-reply@JustinAngel.net");

 

  myMessage.Subject = "simple mail";

  myMessage.Body = "hello justin, how are you today?";

 

  SmtpClient mySmtp = new SmtpClient();

  mySmtp.Host = "127.0.0.1";

  mySmtp.Port = 25;

 

  mySmtp.Send(myMessage);

כל תוכנת דוא"ל מאז 97' בערך תומכת בכך שאם מפורטת כתובת ReplyTo בלחיצה על Reply היא תיקח את כתובת ה-ReplyTo לשליחת תגובה. באופן כללי, זאת מדיניות מאוד טובה ששולחים דוא"ל אוטומטי להוסיף ReplyTo שמכוון את התגובות לדוא"ל.

אנחנו ישראלים טובים וכיאה לכאלו יהיו לנו בעיות עם הקידוד. אז אל תחששו - ניתן לכתוב נושא להודעה ותוכן להודעה באיזה Encoding שרוצים (ואפילו בקידודים שונים כמו בדוגמה לפנינו). בוא נגיד ואנחנו רוצים לשלוח את המייל עם הכותרת "מה שלומך?" ולשאול "מה שלומך גבר גבר?". נשתמש ב-MailMessage.BodyEncoding ו-MailMessage.SubjectEncoding שנותנים לנו לפרט באיזה קידוד להשתמש.

  MailMessage myMessage = new MailMessage();

 

  myMessage.To.Add(new MailAddress("J@JustinAngel.net", "Justin Angel"));

  myMessage.To.Add(new MailAddress("Ayende@ayende.com", "Oren Eini"));

  myMessage.CC.Add(new MailAddress("oren.ellenbogen@hmail.com", "Oren Ellenbogen"));

  myMessage.CC.Add(new MailAddress("royo@oshrovo.com", "Roy Osherove"));

  myMessage.Bcc.Add(new MailAddress("mikiwatts@orb-software.com", "Miki Watts"));

 

  myMessage.From = new MailAddress("mail@JustinAngel.net");

  myMessage.Priority = MailPriority.High;

  myMessage.ReplyTo = new MailAddress("do-not-reply@JustinAngel.net");

 

  myMessage.Subject = "מה שלומך?";

  myMessage.SubjectEncoding = Encoding.Unicode;

  myMessage.Body = "hello justin, how are you today?" + "מה המצב גבר גבר?";

  myMessage.BodyEncoding = Encoding.GetEncoding("iso-8859-8-i");

 

  SmtpClient mySmtp = new SmtpClient();

  mySmtp.Host = "127.0.0.1";

  mySmtp.Port = 25;

כמו בכל הודעת דוא"ל רגילה ניתן להוסיף קבצים כנספחים. ובדומה למענים, מדובר באוסף של קבצים ולא בקובץ יחיד.

  MailMessage myMessage = new MailMessage();

 

  myMessage.To.Add(new MailAddress("J@JustinAngel.net", "Justin Angel"));

  myMessage.To.Add(new MailAddress("Ayende@ayende.com", "Oren Eini"));

  myMessage.CC.Add(new MailAddress("oren.ellenbogen@hmail.com", "Oren Ellenbogen"));

  myMessage.CC.Add(new MailAddress("royo@oshrovo.com", "Roy Osherove"));

  myMessage.Bcc.Add(new MailAddress("mikiwatts@orb-software.com", "Miki Watts"));

 

  myMessage.From = new MailAddress("mail@JustinAngel.net");

  myMessage.Priority = MailPriority.High;

  myMessage.ReplyTo = new MailAddress("do-not-reply@JustinAngel.net");

 

  myMessage.Subject = "מה שלומך?";

  myMessage.SubjectEncoding = Encoding.Unicode;

  myMessage.Body = "hello justin, how are you today?" + "מה המצב גבר גבר?";

  myMessage.BodyEncoding = Encoding.GetEncoding("iso-8859-8-i");

 

  myMessage.Attachments.Add(new Attachment(@"c:\myFile.txt"));

  myMessage.Attachments.Add(new Attachment(GetAttachmentStream(),""));

 

 

  SmtpClient mySmtp = new SmtpClient();

  mySmtp.Host = "127.0.0.1";

  mySmtp.Port = 25;

 

        private static System.IO.Stream GetAttachmentStream()

        {

           return new FileStream(@"c:\myFile.txt", FileMode.Open);

        }

אפשר לראות שהוספנו להודעת הדוא"ל שלנו שני מחלקות מסוג Attachment. המחלקה Attachment מייצגת קובץ שנספח לדוא"ל ויכלה להיווצר או מנתיב מקומי לקובץ או מ-Stream שמכיל את הקובץ.

עד עכשיו שלחנו הודעות טקסטואליות בלבד וכמו שאנחנו יודעים הודעות דוא"ל מכילות תמונות וציורים וטבלאות (ולאחרונה הם גם אומרות לי "שלום" שאני פותח אותן שזה מפחיד בפני עצמו). בכל מקרה, כל אותם משחקי עיצוב הם HTML פשוט. בואו נגיד שלמשל נרצה לשלוח את הטקסט שלנו בתוכן מודגש.

  MailMessage myMessage = new MailMessage();

 

  myMessage.To.Add(new MailAddress("J@JustinAngel.net", "Justin Angel"));

  myMessage.To.Add(new MailAddress("Ayende@ayende.com", "Oren Eini"));

            myMessage.CC.Add(new MailAddress("oren.ellenbogen@hmail.com", "Oren Ellenbogen"));

  myMessage.CC.Add(new MailAddress("royo@oshrovo.com", "Roy Osherove"));

  myMessage.Bcc.Add(new MailAddress("mikiwatts@orb-software.com", "Miki Watts"));

 

  myMessage.From = new MailAddress("mail@JustinAngel.net");

  myMessage.Priority = MailPriority.High;

  myMessage.ReplyTo = new MailAddress("do-not-reply@JustinAngel.net");

 

  myMessage.Subject = "מה שלומך?";

  myMessage.SubjectEncoding = Encoding.Unicode;

  myMessage.Body = "<b>" + "hello justin, how are you today?" + "מה המצב גבר גבר?" + "</b>";

            myMessage.IsBodyHtml = true;

  myMessage.BodyEncoding = Encoding.GetEncoding("iso-8859-8-i");

 

  myMessage.Attachments.Add(new Attachment(@"c:\myFile.txt"));

  myMessage.Attachments.Add(new Attachment(GetAttachmentStream(), ""));

 

 

  SmtpClient mySmtp = new SmtpClient();

  mySmtp.Host = "127.0.0.1";

  mySmtp.Port = 25;

בפשטות, הוספנו את עיצוב ה-HTML שלנו ואמרנו כי MailMessage.IsBodyHtml הוא אמת וזה כל מה שצריך לעשות בשביל תוכן HTMLי. ומכאן השמיים הגבול, טבלאות, צבעים, פונטים, הכל בטוח בפנינו במרחק מאפיין (באנגלית: Property) אחד - IsBodyHtml.

כל זה טוב ויפה, אבל HTML זאת טכנולוגיה מתקדמת. ייתכן וכי יש שירותי דואר שלא תומכים בהצגת HTML גרפי (בכוונה או מחוסר יכולת). כדי לפתור את הבעיה הזאת באו ואמרו ככה - את הדוא"ל הזה אפשר להציג לפי סוג התוכן שביקשת. הכי נפוץ לראות דוא"ל בפורמט text/plain שזה טקסט פשוט ודוא"ל בפורמט text/html שזו תצוגת HTML. אבל יש עוד המון פורמטים, למשל אתמול קיבלתי דוא"ל שמציג טבלה מאוד ארוכה ומורכבת. בתצוגת HTML היה ניתן לראות את הטבלה, בתצוגת טקסט היה אפשר לראות את הטקסט "אנא פתח אוטלוק לתצוגת טבלה" ותצוגה שלישית כמסמך אקסל (!). על כל עניין הפורמטים הזה בנו Namespace שלם בשם System.Net.Mime שהוא האח הקטן והשימושי של System.Net.Mail. בתוך System.Net.Mime יש מחלקה בשם ContentType שמחזיקה סוג פורמט.

עכשיו אתם כנראה קצת מבולבלים "סוג פורמט למה? כל מה שאמרת זה שיש פורמטים, איך אני עובד איתם בתכלס'?". סיכמנו שיש סוגי פורמטים. לכל סוג פורמט כזה ניצור AlternateView לדוא"ל שלנו. כלומר, לכל סוג פורמט ניצור סוג תצוגה אפשרי. לטקסט ניצור תוכן טקסטואלי ול-HTML ניצור תוכן HTMLי. בואו נביט על איך זה נראה.

  MailMessage myMessage = new MailMessage();

 

  myMessage.To.Add(new MailAddress("J@JustinAngel.net", "Justin Angel"));

  myMessage.To.Add(new MailAddress("Ayende@ayende.com", "Oren Eini"));

  myMessage.CC.Add(new MailAddress("oren.ellenbogen@hmail.com", "Oren Ellenbogen"));

  myMessage.CC.Add(new MailAddress("royo@oshrovo.com", "Roy Osherove"));

  myMessage.Bcc.Add(new MailAddress("mikiwatts@orb-software.com", "Miki Watts"));

 

  myMessage.From = new MailAddress("mail@JustinAngel.net");

  myMessage.Priority = MailPriority.High;

  myMessage.ReplyTo = new MailAddress("do-not-reply@JustinAngel.net");

 

  myMessage.Subject = "מה שלומך?";

  myMessage.SubjectEncoding = Encoding.Unicode;

 

  myMessage.Attachments.Add(new Attachment(@"c:\myFile.txt"));

  myMessage.Attachments.Add(new Attachment(GetAttachmentStream(), ""));

 

  ContentType PlainContentType = new ContentType("text/plain");

  AlternateView PlainView = AlternateView.CreateAlternateViewFromString

    ("Hi justin, how are you?", PlainContentType);

  myMessage.AlternateViews.Add(PlainView);

 

  ContentType HtmlContentType = new ContentType("text/html");

  AlternateView HtmlView = AlternateView.CreateAlternateViewFromString

    ("<b>Hi justin, how are you?</b>", HtmlContentType);

  myMessage.AlternateViews.Add(HtmlView);

 

 

  SmtpClient mySmtp = new SmtpClient();

  mySmtp.Host = "127.0.0.1";

  mySmtp.Port = 25;

עשינו משהו מאוד פשוט - הוספנו ContentType חדש, הוספנו AlternateView לאותו סוג פורמט ואת אותו AlternateView הוספנו ל-MailMessage.AlternateViews (שזה אוסף של AlternateViews). וככה אנחנו יכולים מאוד בקלות ליצור כמה תצוגות שצריך לדוא"ל שלנו. סה"כ זה מנהג מאוד טוב להוסיף AlternateView אחד ל-HTML ו-AlternateView אחד לטקסט פשוט.

אם בחנתם את הדוגמה לעיל לעומק שמתם כנראה לב שביצעתי מחטף קטן, העלמתי את העברית מהדוא"ל. אז בואו נחליף את התצוגה הטקסטואלית לעברית פשוטה ונוסיף קידוד בהתאם.

  MailMessage myMessage = new MailMessage();

 

  myMessage.To.Add(new MailAddress("J@JustinAngel.net", "Justin Angel"));

  myMessage.To.Add(new MailAddress("Ayende@ayende.com", "Oren Eini"));

  myMessage.CC.Add(new MailAddress("oren.ellenbogen@hmail.com", "Oren Ellenbogen"));

  myMessage.CC.Add(new MailAddress("royo@oshrovo.com", "Roy Osherove"));

  myMessage.Bcc.Add(new MailAddress("mikiwatts@orb-software.com", "Miki Watts"));

 

  myMessage.From = new MailAddress("mail@JustinAngel.net");

  myMessage.Priority = MailPriority.High;

  myMessage.ReplyTo = new MailAddress("do-not-reply@JustinAngel.net");

 

  myMessage.Subject = "מה שלומך?";

  myMessage.SubjectEncoding = Encoding.Unicode;

 

  myMessage.Attachments.Add(new Attachment(@"c:\myFile.txt"));

  myMessage.Attachments.Add(new Attachment(GetAttachmentStream(), ""));

 

            myMessage.BodyEncoding = Encoding.UTF8;

 

  ContentType PlainContentType = new ContentType("text/plain");

            AlternateView PlainView = AlternateView.CreateAlternateViewFromString

    ("אהלן ג'סטין, מה המצב גבר גבר?", PlainContentType);

  PlainView.TransferEncoding = TransferEncoding.Base64;

  myMessage.AlternateViews.Add(PlainView);

 

 

  ContentType HtmlContentType = new ContentType("text/html");

  AlternateView HtmlView = AlternateView.CreateAlternateViewFromString

              ("<b>Hi justin, how are you?</b>", HtmlContentType);

  myMessage.AlternateViews.Add(HtmlView);

 

 

  SmtpClient mySmtp = new SmtpClient();

  mySmtp.Host = "127.0.0.1";

  mySmtp.Port = 25;

 

AlternateView הוא למעשה סוג של Attachment לדוא"ל ולכן הוא קצת יותר מוגבל מבחינת קידוד (TransferEncoding הוא Enum יחסית מוגבל שמתייחס לקידוד בו מועבר הקובץ). זאת בזמן ש-MailMessage.BodyEncoding מתייחס לקידוד שבו תוצג ההודעה.

קודם דיברנו על תמונות כחלק מהדוא"ל ודוא"ל מדבר. אז דוא"ל מדבר לא נדגים כאן, אבל תמונה אין למה לא.

נשתמש בחלק האחרון של AlternateView - ב-LinkedResources. אוסף זה מאפשר לנו להוסיף קובץ שיהיה חלק מהמסמך ולא כקובץ כנספח חיצוני למסמך. את ה-LinkedResource ניתן ליצור (בדומה ל-Attachment) מתוך נתיב לקובץ או מתוך Stream שמכיל את הקובץ. בואו נראה דוגמה להוספת תמונה שלי בראש המסמך וכרטיס ביקור בסיומו.

          MailMessage myMessage = new MailMessage();

 

  myMessage.To.Add(new MailAddress("J@JustinAngel.net", "Justin Angel"));

  myMessage.To.Add(new MailAddress("Ayende@ayende.com", "Oren Eini"));

  myMessage.CC.Add(new MailAddress("oren.ellenbogen@hmail.com", "Oren Ellenbogen"));

  myMessage.CC.Add(new MailAddress("royo@oshrovo.com", "Roy Osherove"));

  myMessage.Bcc.Add(new MailAddress("mikiwatts@orb-software.com", "Miki Watts"));

 

  myMessage.From = new MailAddress("mail@JustinAngel.net");

  myMessage.Priority = MailPriority.High;

  myMessage.ReplyTo = new MailAddress("do-not-reply@JustinAngel.net");

 

  myMessage.Subject = "מה שלומך?";

  myMessage.SubjectEncoding = Encoding.Unicode;

 

  myMessage.Attachments.Add(new Attachment(@"c:\myFile.txt"));

  myMessage.Attachments.Add(new Attachment(GetAttachmentStream(), ""));

 

  myMessage.BodyEncoding = Encoding.UTF8;

 

            ContentType PlainContentType = new ContentType("text/plain");

  AlternateView PlainView = AlternateView.CreateAlternateViewFromString

    ("אהלן ג'סטין, מה המצב גבר גבר?", PlainContentType);

  PlainView.TransferEncoding = TransferEncoding.Base64;

  myMessage.AlternateViews.Add(PlainView);

 

 

  ContentType HtmlContentType = new ContentType("text/html");

  AlternateView HtmlView = AlternateView.CreateAlternateViewFromString

              ("<img src=cid:JustinPic><b>Hi justin," +

       "how are you?</b><img src=cid:JustinBusinessCard>", HtmlContentType);

       

            LinkedResource SomePic = new LinkedResource(@"c:\Justin-02-02-2006.gif");

  SomePic.ContentId = "JustinPic";

  HtmlView.LinkedResources.Add(SomePic);

 

  LinkedResource SomeOtherPic = new LinkedResource(GetBusinessCardStream());

  SomeOtherPic.ContentId = "JustinBusinessCard";

  HtmlView.LinkedResources.Add(SomeOtherPic);

 

  HtmlView.LinkedResources.Add(new LinkedResource(@"c:\JustiPic.gif"));

  myMessage.AlternateViews.Add(HtmlView);

 

 

  SmtpClient mySmtp = new SmtpClient();

  mySmtp.Host = "127.0.0.1";

  mySmtp.Port = 25;

 

 

        private static Stream GetBusinessCardStream()

        {

  return new FileStream(@"c:\Bizcard.jpg", FileMode.Open);

 

       }

        private static Stream GetAttachmentStream()

        {

           return new FileStream(@"c:\myFile.txt", FileMode.Open);

        }

בואו נעבור על מה שעשינו, דבר ראשון יצרנו LinkedResource שנובע מקובץ מקומי או Stream. נתנו לאותו LinkedResource.ContentId שתסמל אותו שנעבוד בתוך המסמך. בתוך המסמך, כחלק מה-HTML מוכר יצרנו תגית <img> עם ווריציה קלה - כתבנו src=cid:myLinkedResourceContentId. אגב, בכוונה נתתי לקבצים ולמחלקות LinkedResource שמות לא קשורים כדי שתראו בדיוק מאיפה מגיע ה-ContentId.

 

חלק ד': חוקרים את SmtpClient (או: "סינכרוני\א-סינכרוני, מאובטח\לא-מאובטח ומשלוח מקומי או משלוח ברשת")

עד עכשיו עבדנו על אובייקט ה-MailMessage שהוא התוכן שנשלח ולא דיברנו כמעט בכלל על SmtpClient שהוא השולח עצמו. בואו ננקה את הדוגמה שלנו מקודם ונעבוד עם מתודה אחת גדולה שמייצרת לנו את ה-MailMessage בכדי שנוכל להתמקד ב-SmtpClient.

            MailMessage myMessage = CreateVeryComplexMailMessage();

  myMessage.From = new MailAddress("mail@JustinAngel.net");

 

  SmtpClient mySmtp = new SmtpClient();

  mySmtp.Host = "127.0.0.1";

  mySmtp.Port = 25;

 

  mySmtp.Send(myMessage);

 

 

        private static MailMessage CreateVeryComplexMailMessage()

        {

  MailMessage myMessage = new MailMessage();

 

  myMessage.To.Add(new MailAddress("J@JustinAngel.net", "Justin Angel"));

  myMessage.To.Add(new MailAddress("Ayende@ayende.com", "Oren Eini"));

  myMessage.CC.Add(new MailAddress("oren.ellenbogen@hmail.com", "Oren Ellenbogen"));

  myMessage.CC.Add(new MailAddress("royo@oshrovo.com", "Roy Osherove"));

  myMessage.Bcc.Add(new MailAddress("mikiwatts@orb-software.com", "Miki Watts"));

 

  myMessage.Priority = MailPriority.High;

  myMessage.ReplyTo = new MailAddress("do-not-reply@JustinAngel.net");

 

  myMessage.Subject = "מה שלומך?";

  myMessage.SubjectEncoding = Encoding.Unicode;

 

  myMessage.Attachments.Add(new Attachment(@"c:\myFile.txt"));

  myMessage.Attachments.Add(new Attachment(GetAttachmentStream(), ""));