Building an E-Mail Business Service


Building a mail services layer for an enterprise application requires interaction with the presentation layer clients , internal business objects, the database, and the underlying mail system.

The purpose of the mail services layer is to provide a high-level interface for mail sending functions. For example, when a new issue is entered, IssueTracker might be configured to notify a specific team member. In this case, the New Issue user interface invokes a method within the mail services layer. This method accesses the database to obtain the destination user's e-mail address, the configurable message text, and the application's mail settings.

To implement the e-mail business service, open the IssueTracker project in Visual Studio .NET and select the Business Facade project in the Solution Explorer. From the menu, choose Project ˜ Add Class and enter EmailService.cs as the item name . Visual Studio .NET will create a new source file for the EmailService class.

The process of programmatically sending messages happens in three parts : creating the message, appending attachments, and sending. The .NET Framework packages e-mail sending functionality into the System.Web.Mail namespace. Listing 5-2 shows the e-mail business service definition.

Listing 5-2: The E-Mail Business Service Definition
start example
 public class EmailService : BusinessService {     private User _UserFrom = new User();     private User _UserTo = new User();     private User _UserCc = new User();     private User _UserBcc = new User();     private MailMessage _OutgoingMessage = new MailMessage();     private ArrayList _IncomingMessages = new ArrayList();     public EmailService()     {     } } 
end example
 

Because the EmailService class is going to access the .NET Framework's e-mail classes, you will need to add a reference to the System.Web namespace. Therefore, select the Business Facade project in the Solution Explorer and choose Project ˜ Add Reference from the menu. The Add Reference dialog box will appear, as shown in Figure 5-5. In the .NET tab, select System.Web.dll from the component list and click Select, then OK. A reference will be added under the Business Facade References folder.

click to expand
Figure 5-5: Adding the assembly reference to the System.Web namespace

After you have added the reference to the Business Facade project, add the namespace reference to the top of the EmailService class definition:

 using System.Web.Mail; 

Sending Messages

After you have created a message, you need to send it. The message can be delivered either through the SMTP mail service built into Microsoft Windows 2000 or through a designated SMTP server. The .NET Framework abstracts the SMTP mail server with the SmtpMail object. This object interacts with the underlying mail services to process the outgoing message. In most cases, this requires a system-level interaction with the Collaboration Data Objects for Windows 2000 (CDOSYS) message component.

To send messages with the SmtpMail object, first designate the location of the SMTP mail server. By default, mail is queued on a Windows 2000 system, ensuring that the calling program does not block network traffic. If you set the SmtpServer property, you deliver the mail directly to the specified server.

The final step in the mail sending process is to call the SmtpMail object's Send method. This method takes a single parameter that represents the initialized MailMessage object complete with content and attachments. The resulting code appears in Listing 5-3.

Listing 5-3: The SendMessage Method Implemented in the EmailService Object
start example
 public void SendMessage() {     try     {          //assign 'to' user          _OutgoingMessage.To = _UserTo.EmailAddress;          //assign 'cc' user          _OutgoingMessage.Cc = _UserCc.EmailAddress;          //assign 'bcc' user          _OutgoingMessage.Bcc = _UserBcc.EmailAddress;          //assign the 'from' user          _OutgoingMessage.From = _UserFrom.EmailAddress;          SmtpMail.SmtpServer = "127.0.0.1";          SmtpMail.Send(_OutgoingMessage);     }     catch(Exception x)     {         LogEvent(x.Message);     }     return; } 
end example
 

The MailMessage object abstracts all aspects of a message including its addressing, content, and attachments. Sending an e-mail message begins by setting the message destination and origination values of the message with the To, Cc, Bcc, and From properties. These properties accept one or more e-mail addresses separated by a emicolon.

Next , set the e-mail message attributes such as encoding, format, and priority. The encoding should be one of the System.Text.Encoding enumerated types that define the target character set. You must define the format of the message as either plain text or as HTML. The MailPriority enumeration indicates the urgency of the message as Low, Normal, or High. With the message attributes well defined, you are ready to add the content of the message. Two properties define the message content: the subject and the body. The subject is summary text that identifies what the message is about, and the body is the full detail of the message.

In the application code, the task of sending an e-mail message has been simplified by the .NET Framework services. Listing 5-4 outlines the application code.

Listing 5-4: EmailService Client Code
start example
 private void SendAlertToUser() {     User userTo = new User();     userTo.EmailAddress = "sendto@something.com";     User userFrom = new User();     userFrom.EmailAddress =  "sentfrom@something.com";     User userCc = new User();     userCc.EmailAddress = "copyto@something.com";     User userBcc = new User();     userBcc.EmailAddress =  "blindcopyto@something.com";     MailMessage message = new MailMessage();     message.Subject = "IssueTracker Alert";     message.Body = "A new issue has been assigned to you.";     EmailService mail = new EmailService();     mail.SendTo = userTo;     mail.SendCc = userCc;     mail.SendBcc = userBcc;     mail.SentFrom = userFrom;     mail.OutgoingMessage = message;     mail.SendMessage();     return; } 
end example
 

First, the application code must include the System.Web.Mail namespace to reference the MailMessage object. Second, the User objects are instantiated to capture the To, From, Cc, and Bcc e-mail addresses. Next, the MailMessage object is instantiated , and the User objects are assigned to it. Next, the message formatting is set to a plain-text message with Normal delivery priority. The message subject and body are also set to the parameters supplied to this method. Finally, the SendMessage method is called to send the message to its destination.

Appending Attachments

E-mail message sent through the .NET Framework can have any number of file attachments. There is no restriction on the file type or size of message attachments. These files typically range from small text files or documents to large images or even compressed packages of files.

To programmatically associate a file attachment to an outgoing e-mail message, begin by creating and initializing the MailMessage object. Next, create and initialize a MailAttachment object, passing a logical file path to the source document:

 MailAttachment attachment = new MailAttachment("c:\IssueTracker\sample.txt"); 

Alternatively, you can supply the attachment filename as a property value of the MailAttachment object:

 attachment.Filename = "c:\IssueTracker\sample.txt"; 

Next, specify the encoding of the message attachment. Encoding converts binary data into a series of ASCII characters that can be transmitted over the Internet. The two most common specifications for attachment encoding are UUEncode and Base64. UUEncode originally stood for Unix-to-Unix Encode , but it has become a universal protocol used to transfer files between different platforms such as Unix, Windows, and Macintosh. UUEncode converts data into a series of 7-bit characters that can be transmitted over the Internet. Base64 encoding converts data into a series of 6-bit characters, consistently keeping encoded data about 33 percent larger than the original data. By default, Base64 encoding is used for attachment encoding:

 attachment.Encoding = System.Web.Mail.MailEncoding.Base64; 

After you have created the MailAttachment object, pointed it to the source file, and encoded it, you can finally bind it to the MailMessage object. Invoke the Add method in the Attachments collection:

 mail.Attachments.Add(attachment); 

You can add any number of attachments to the MailMessage object by changing the filename and calling the Add method. When the message is sent, the .NET Framework will locate the referenced files, encode them as specified, and transmit them along with the outgoing message. Listing 5-5 shows the EmailService client code that sends an attachment with the message.

Listing 5-5: EmailService Client Code with an Attachment
start example
 private void SendAlertToUser() {     User userTo = new User();     userTo.EmailAddress = "sendto@something.com";     User userFrom = new User();     userFrom.EmailAddress =  "sentfrom@something.com";     User userCc = new User();     userCc.EmailAddress = "copyto@something.com";     User userBcc = new User();     userBcc.EmailAddress =  "blindcopyto@something.com";     MailMessage message = new MailMessage();     message.Subject = "IssueTracker Alert";     message.Body = "A new issue has been assigned to you.";     EmailService mail = new EmailService();     mail.SendTo = userTo;     mail.SendCc = userCc;     mail.SendBcc = userBcc;     mail.SentFrom = userFrom;     mail.OutgoingMessage = message;     MailAttachment attachment = new MailAttachment();     attachment.Filename = "c:\IssueTracker\sample.txt";     attachment.Encoding = System.Web.Mail.MailEncoding.Base64;     mail.Attachments.Add(attachment);     mail.SendMessage();     return; } 
end example
 

Sending an Object-Driven Message

In addition to sending messages from one user to another, the EmailService class will support automated messages that require only a recipient e-mail address and message template. The message template will represent a specific automated message stored in the database. The message subject, body, type, delivery type will all come from the database to build a message that is automatically sent to another user when certain conditions are met. Storing automated message information in a database helps keep the messages maintainable and easier for future translation into foreign languages. A typical use for this method is for an automated message that is sent to an administrator each time a new issue is entered. Listing 5-6 shows the MailMessageTemplate business object.

Listing 5-6: The MailMessageTemplate Business Object
start example
 public class MailMessageTemplate : BusinessObject {     public MailMessageTemplate()     {     }     public int MailMessageID = 0;     public int Format = 0;     public int Priority = 0;     public string Subject = "";     public string Body = ""; } 
end example
 

Now that the basic User and MailMessageTemplate business objects exist, you must add property accessor methods to the EmailService object (see Listing 5-7).

Listing 5-7: Adding Property Accessors to the EmailService Object
start example
 public User SendTo {          get          {              return _UserTo;          }          set          {              _UserTo = value;          } } public User SendCc {     get     {          return _UserCc;     }     set     {          _UserCc = value;     } } public User SendBcc {     get     {          return _UserBcc;     }     set     {          _UserBcc = value;     } } public User SentFrom {     get     {          return _UserFrom;     }     set     {          _UserFrom = value;     } } public MailMessage OutgoingMessage {     get     {         return _OutgoingMessage;     }     set     {         _OutgoingMessage = value;     } } 
end example
 

Another implementation of the SendMessage method is an object-driven version that accepts a MailMessageTemplate object and an Issue object. Because this method depends upon reflection objects, you must specify the System.Reflection namespace in the code. Listing 5-8 shows a sample template for an object-driven message.

Listing 5-8: Sample E-Mail Template for an Object-Driven Message
start example
 Dear Administrator, Issue # <Issue.IssueID> was filed on <Issue.Date>. The description of the new Issue is: <Issue.Summary> <Issue.Description> Sincerely, IssueTracker Auto-mailer 
end example
 

Listing 5-9 shows how to implement the object-driven SendMessage method within EmailService.

Listing 5-9: Implementing the Object-Driven SendMessage Method within EmailService
start example
 public void SendMessage(MailMessageTemplate argTemplate, Issue argIssue) {     int intStart = 0;     int intEnd = 0;     string strField = "";     string strValue = "";     string strSource = "";     Type objType;     FieldInfo field;     try     {          //fill the message template          strSource = argTemplate.Body;          while(intStart >= 0)          {              //find the start              intStart = strSource.IndexOf("<Issue.", intStart) + 7;              //find the end              intEnd = strSource.IndexOf(">", intStart);              //get the field name              strField = strSource.Substring(intStart, intEnd - intStart);              objType = argIssue.GetType();              field = objType.GetField(strField);              strValue = field.GetValue(objType).ToString();              strSource = strSource.Replace("<Issue." + strField + ">", strValue);          };          //set the outgoing message          MailMessage _OutgoingMessage = new MailMessage();          _OutgoingMessage.To = _UserTo.EmailAddress;          _OutgoingMessage.Cc = _UserCc.EmailAddress;          _OutgoingMessage.Bcc = _UserBcc.EmailAddress;          _OutgoingMessage.From = _UserFrom.EmailAddress;          _OutgoingMessage.Subject = argTemplate.Subject;          _OutgoingMessage.Body = strSource;          //send the messsage          SmtpMail.SmtpServer = "localhost";          SmtpMail.Send(_OutgoingMessage);     }     catch(Exception x)     {         LogEvent(x.Message);     }     return; } 
end example
 

This method begins by retrieving the message details from the message template. Next, the user information is retrieved from the attached EmailService User objects. Once the message and user information is available, the rest of the method works similarly to the SendSimpleMessage method. The MailMessage object is created and assigned properties such as From, To, BodyFormat, Priority, Subject, and Body. Finally, the Send method in the SmtpMail object is called to send the message to its destination.

This method implements a simple parser to replace tokens in the mail message template with business object values. Although this solution meets basic needs, a more flexible solution would be to leverage XSL Transformations (XSLT) to accommodate the replacements . Chapter 9, "Using XML and Web Services," takes a close look at Extensible Markup Language (XML) and its related technologies, such as XSLT.

Retrieving E-Mail Messages

As mentioned earlier, the .NET Framework does not natively support the ability of reading e-mail messages from a mail server. Therefore, this method will use the CDO object library to check the mail server for customer messages. The mail messages that IssueTracker will listen for are those with a specific destination address created for IssueTracker to use. Later, IssueTracker will provide a link on a Web page for customer support questions. This link will be a mailto link that triggers the customer's e-mail client to open with the addressee and subject lines filled in:

 <a href="mailto:issuetracker@company.com?subject=IssueTracker Submission   "> Send message to customer support.</a> 

This link displays the text Send message to customer support in the Web page. When clicked, a new e-mail message form is displayed with the default addressee set to <issuetracker@company.com> and the default subject line set to IssueTracker Submission....

Begin by adding a project reference. With the Business Facade project in the Solution Explorer selected, choose Project ˜ Add Reference from the Visual Studio .NET menu. Select the COM tab. In the Windows XP environment, find the Microsoft CDO for Exchange 2000 Library component, click Select, and then click OK (see Figure 5-6). In the Windows 2000 environment, the component name will be Microsoft Outlook 9.0 Object Library. A reference to CDO and Outlook will appear in the Solution Explorer, and the CDO services will become accessible.

click to expand
Figure 5-6: Adding the COM component reference to the Microsoft CDO object library

Once you have added the CDO and Outlook references, you can implement the functional code to scan the Inbox and return a collection of messages. This method begins with local variable declarations. Listing 5-10 shows how to implement the GetMail method in the EmailService Object.

Listing 5-10: Implementing the GetMail Method in the EmailService Object
start example
 public ArrayList GetMail() {     MailMessage message;     Outlook.MailItem msgInbox;     ArrayList arrayMessages = null;     Outlook.ApplicationClass appOutlook = null;     try     {         arrayMessages = new ArrayList();         //connect to the CDO library         appOutlook = new Outlook.ApplicationClass();         Outlook.NameSpace appNamespace = appOutlook.GetNamespace("MAPI");         appNamespace.Logon("jkanalakis", "jkanalakis", false, false);         //navigate to the inbox folder         Outlook.Explorer exp = appOutlook.Explorers.Item(1);         for(int intIdx = 1; intIdx <= exp.CurrentFolder.Items.Count; intIdx++)         {             //retrieve the next message from the inbox             msgInbox = (Outlook.MailItem)exp.CurrentFolder.Items.Item(intIdx);             //convert data into MailMessage             message = new MailMessage();             message.Subject = msgInbox.Subject;             message.Body = msgInbox.Body;             //add MailMessage to the ArrayList             arrayMessages.Add(message);         }     }     catch(Exception exception)     {         LogEvent(x.Message);     }     finally     {         Marshal.ReleaseComObject(appOutlook);     }     return arrayMessages; } 
end example
 

Because this method returns an ArrayList containing MailMessage objects, you must include the System.Collections namespace. Next, you connect to the CDO object by creating an ApplicationClass object. Next, you create a NamespaceClass object and point it to the MAPI namespace. Then, you can log into the Outlook session by supplying a username and password. After logging in, an Explorer object is created to help navigate the CDO object hierarchy and point to the Inbox folder. Once pointed to the Inbox, you can iterate through the Items array. Because all CDO e-mail messages are represented by a MailItem data type, this method performs a mapping of data fields into a MailMessage object. The assembled MailMessage object is then added to the ArrayList collection. Any exceptions thrown during execution are caught and logged for future reference. Finally, the ReleaseComObject method forces the runtime-callable wrapper to release the COM object reference, and the filled array of MailMessage objects returns to the calling application.

This method provides an easy approach for an application to scan an Inbox and return a collection of MailMessage objects. The application can then iterate through the message collection for display or keyword search.




Developing. NET Enterprise Applications
Developing .NET Enterprise Applications
ISBN: 1590590465
EAN: 2147483647
Year: 2005
Pages: 119

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net