2011-09-23 220 views
3

我正在考虑使用提供商模式创建电子邮件提供商。我们的电子邮件系统处于混乱状态。我们在同一个应用程序以及不同的应用程序中使用自己的处理电子邮件的方式有不同的区域。我想创建一个电子邮件提供商,因为全线的信息大致相同。通过使用提供者模式,我可以使用我们的默认处理电子邮件的方式,但也可以使用接口,我可以引入更多特定/自定义电子邮件处理。电子邮件提供商设计

所以我不太清楚我将如何设置界面来处理每个区域特定/自定义处理,并正在寻找一些指导。我希望我的抽象类能够容纳默认设置/功能,然后让我的电子邮件提供商执行对sproc的调用以发送电子邮件。

现在不知道我将如何引入一个新界面,以便如果另一个开发人员需要执行与他正在开发的区域有关的一些定制,他可以扩展提供程序以处理其更改。这种方法的任何想法或可能建议其他方法?如果你喜欢提供者的方法,并知道如何实现我所建议的一些伪代码会很好。 :)

public Interface IEmail 

abstract class EmailProviderBase : ProviderBase, IEmail 

    //Default settings and methods 
    public virtual SendEmail(){} 


//Used to handle default implementation 
public class EmailProvider : EmailProviderBase 

//But want other classes to be used to handle other devs custom implementations 
//I guess I could create another provider per say based on EmailProviderBase. 
public class CustomEmail : EmailProviderBase 

有谁能告诉我他们是否喜欢这种方法?如果不是,你将如何使用接口来设计它?

感谢, DND

回答

2

这可能只是我,但在我看来,System.Net.Mail类已经这样做了抽象的细节一个良好的工作和罢工的可定制性和易用性之间的良好平衡。如果您尝试简化更多,您将失去在需要时自定义的能力。

我们开始沿着这条道路做电子邮件,当我们做了更多的项目,并且我们的需求改变了,我们最终不得不定制我们的班级,以至于显然整个练习是浪费时间。

但是,我知道你来自哪里,这里有另一种统一如何从应用程序发送电子邮件的可能性。这不是你要求的,而是根据我们团队的工作原理,以一种可能的不同方式来处理问题。

我们的决定基于SOLELY对我们最大的痛点,那就是我们的管理员每隔几年就会换出Exchange服务器,或者他们会因为某种原因更改IP地址。每次发生这种情况时,我们都必须重新编译一堆代码,这非常令人沮丧。

我们最终设置了一个具有电子邮件功能的Web服务。现在,我们内部应用中的所有电子邮件都使用Web服务。当我们的管理员更改服务器上的某些内容时,我们只需要调整Web服务中的.config文件,而不必在每个发送电子邮件的应用程序中重新编译或编辑.config。

这对我们特别有效,因为我们能够将错误处理集成到我们的中央错误记录数据库中,所以我们所有的应用程序都只有几行代码来发送电子邮件。错误处理是免费的。

自从我们实现这个以来,唯一必须做的调整是让Web服务通过PickupDirectory发送电子邮件,而不是直接与Exchange服务器通信。这允许服务在Exchange服务器关闭时进行工作(维护,重新启动以应用修补程序等)。)

Web服务中的代码也相当简单,并使用Microsoft.Security.AntiXss组件处理卫生。

代码中对监督系统的引用是对我们的中央错误记录数据库的引用。我不打算包含该代码,因为这已经太长了答案,而且它确实会将错误记录到SQL数据库。

对不起,它是在你指定C#的VB中,但如果你有兴趣,它应该很容易转换。

<WebMethod()> _ 
Public Function SendEmailViaPickupDir(ByVal FromAddress As String, ByVal ToList As String, ByVal CcList As String, ByVal BccList As String, _ 
        ByVal Subject As String, ByVal MessageBody As String, ByVal IsBodyHtml As Boolean) As Boolean 

    Dim msg As System.Net.Mail.MailMessage = BuildMessage(FromAddress, ToList, CcList, BccList, Subject, MessageBody, IsBodyHtml) 

    If Not msg Is Nothing Then 
     Return SendMessageViaPickupDir(msg) 
    Else 
     Return False 
    End If 

End Function 

Private Function BuildMessage(ByVal FromAddress As String, ByVal ToList As String, ByVal CcList As String, ByVal BccList As String, _ 
    ByVal Subject As String, ByVal MessageBody As String, ByVal IsBodyHtml As Boolean) As System.Net.Mail.MailMessage 

    Dim msg As New System.Net.Mail.MailMessage 

    Try 
     msg.From = New System.Net.Mail.MailAddress(FromAddress) 

     If Not ToList Is Nothing Then 
      For Each Address As String In ToList.Split(";".ToCharArray(), StringSplitOptions.RemoveEmptyEntries) 
       msg.To.Add(New System.Net.Mail.MailAddress(Address.Trim())) 
      Next 
     End If 

     If Not CcList Is Nothing Then 
      For Each Address As String In CcList.Split(";".ToCharArray(), StringSplitOptions.RemoveEmptyEntries) 
       msg.CC.Add(New System.Net.Mail.MailAddress(Address.Trim())) 
      Next 

     End If 
     If Not BccList Is Nothing Then 
      For Each Address As String In BccList.Split(";".ToCharArray(), StringSplitOptions.RemoveEmptyEntries) 
       msg.Bcc.Add(New System.Net.Mail.MailAddress(Address.Trim())) 
      Next 

     End If 

     msg.Subject = Microsoft.Security.Application.AntiXss.HtmlEncode(Subject) 
     If (IsBodyHtml) Then 
      msg.Body = Microsoft.Security.Application.AntiXss.GetSafeHtmlFragment(MessageBody) 
     Else 
      ' This was causing formatting issues... 
      msg.Body = MessageBody 
     End If 
     msg.IsBodyHtml = IsBodyHtml 

    Catch ex As Exception 
     Dim s As New OverseerService 
    s.WriteToSql(Convert.ToInt64(ConfigurationManager.AppSettings("OverseerWebSiteResourceid")), User.Identity.Name, _ 
    My.Computer.Name, ex.ToString(), MyCompany.Overseer.EventLogger.SeverityLevel.Critical) 
     Return Nothing 
    End Try 

    Return msg 

End Function 

Private Function SendMessageViaPickupDir(ByVal msg As System.Net.Mail.MailMessage) As Boolean 
    Dim ret As Boolean = False 

    Try 
     ' try to send through pickup dir 
     Dim c1 As New System.Net.Mail.SmtpClient("localhost") 
     c1.DeliveryMethod = Net.Mail.SmtpDeliveryMethod.PickupDirectoryFromIis 
     c1.Send(msg) 
     ret = True 

    Catch ex As Exception 
     Try 
      ' log as a known error 
      Dim s As New OverseerService 
      s.WriteToSql(Convert.ToInt64(ConfigurationManager.AppSettings("OverseerWebSiteResourceid")), User.Identity.Name, _ 
      My.Computer.Name, "failed to write email to pickup dir " + ex.ToString(), MyCompany.Overseer.EventLogger.SeverityLevel.KnownError) 
     Catch 
      ' ignore error from writing the error 
     End Try 
    End Try 

    Return ret 

End Function 
+1

戴夫 - 我喜欢这个想法使用的Web服务。我想如果我通过数据库发送电子邮件,我可以实现更灵活的架构设计。我也可以将我的电子邮件提供商设计也纳入其中。你怎么看? – DotNetDude

+1

您可能可以通过电子邮件发送数据库。我不知道这是否会是更好的选择。我必须尝试调查。我们几乎坚持这种设计,因为它消除了我们所有的痛苦,并且对我们来说工作得非常好,但是如果您想进一步改进它,那么您会获得更多的权力! – David

+0

好的感谢您的回复! – DotNetDude

1

你签出了http://mailsystem.codeplex.com/?这可能是codeplex上最复杂的OSS电子邮件工具。在codeplex上有一个更简单的产品,更类似于上面所描述的,但我现在没有任何运气可以找到它。

+0

听起来很有趣。将进一步研究。感谢回复! – DotNetDude