Una de las características que nos encontramos cuando tenemos alojado DotNetNuke en Azure es que no disponemos de un servidor SMTP para el envío de los correos de notificación que usa el gestor de contenidos.
La solución pasa por una de las siguientes alternativas muy bien expuestas en el post de Christian Weyer:
-
Usar un proveedor externo que pueda ayudar en el envío de correos
-
Conectar a tu servidor SMTP On-Premises
-
Usar APIs/Servicios expuestos por terceros para el envío
Bajo el último enfoque entran los servicios expuestos por Exchange Online, servicio que a través del pago de 5$ al mes/usuario podemos contar con la capacidad de un servidor de Exchange alojado en la nube –recordad que podéis probar la suite BPOS durante un periodo de 30 días sin compromiso.
Para usar los servicios de Exchange Online desde DNN realizaremos una serie de modificaciones en el portal para usar los servicios web que nos ofrece. El WSDL de estos servicios está accesible según la región donde se hayan solicitado los mismos:
Asia y Pacífico (APAC) | https://red003.mail.apac.microsoftonline.com/ews/Services.wsdl |
Europa (EMEA) | https://red002.mail.emea.microsoftonline.com/ews/Services.wsdl |
Norte América (NA) | https://red001.mail.microsoftonline.com/ews/Services.wsdl |
El WSDL nos ofrece una completa información acerca de los webmethods disponibles para operar remotamente con Exchange, aunque para simplificar su uso utilizaremos la EWS Managed API 1.1, que podéis descargar desde este enlace.
En los pasos siguientes vamos a realizar unas pequeñas modificaciones en nuestro portal DNN para usar estos servicios web de Exchange Online.
Modificar el DNN core para conectar con BPOS
Como lo que deseamos es ampliar la funcionalidad actual del DNN para soportar BPOS y permitir seguir seleccionando un servidor SMTP, comencemos por modificar las opciones de configuración del host –para realizar estas modificaciones será necesario disponer del código fuente de DotNetNuke Community, que pueden descargar la última versión desde este enlace.
1. Añadir el enumerado MailServerType en el proyecto DotNetNuke.Library, en el archivo LibraryServicesMailMailServerType.vb (crear el archivo):
Namespace DotNetNuke.Services.Mail
Public Enum MailServerType
SMTP
BPOS
End Enum
End Namespace
2. Añadimos en la clase DotNetNuke.Entities.Host.Host la propiedad MailServerType:
''' <summary>
''' Gets the MailServerType (SMTP or BPOS)
''' </summary>
Public Shared ReadOnly Property MailServerType As DotNetNuke.Services.Mail.MailServerType
Get
Return CType(HostController.Instance.GetInteger("MailServerType"), DotNetNuke.Services.Mail.MailServerType)
End Get
End Property
3. Agregamos una referencia a la EWS Managed API. La instalación no la coloca en la GAC para prevenir problemas con otras posibles instalaciones futuras –ese es el motivo que pone en la documentación-, así que tenemos que buscar la librería que por defecto se instala en la ruta: C:Program FilesMicrosoftExchangeWeb Services1.1Microsoft.Exchange.WebServices.dll. Aseguraos de poner el ensamblado como “Copia local=true” para que se copie automáticamente el ensamblado en el “bin” de DotNetNuke al generar el core.
4. Importar el espacio de nombres Microsoft.Exchange.WebServices.Data a través de las propiedades del proyecto
5. Añadir un discriminador en la rutuna SendMail de la clase “Mail” para detectar si el envío es a través de Exchange Online:
' Send using BPOS instead of SMTP
If Host.MailServerType = MailServerType.BPOS AndAlso SMTPServer = Host.SMTPServer Then
Return SendMailBPOS(MailFrom, MailTo, Cc, Bcc, ReplyTo, Priority, Subject, BodyFormat, BodyEncoding, Body, Attachments, SMTPServer, SMTPUsername, SMTPPassword)
End If
6. Agregar la rutina del envío de mensajes usando la API de Exchange:
Public Shared Function SendMailBPOS(ByVal MailFrom As String, ByVal MailTo As String, _ ByVal Cc As String, ByVal Bcc As String, ByVal ReplyTo As String, _ ByVal Priority As MailPriority, ByVal Subject As String, _ ByVal BodyFormat As MailFormat, ByVal BodyEncoding As System.Text.Encoding, ByVal Body As String, _ ByVal Attachments As List(Of Attachment), ByVal WebServiceURL As String, _ ByVal Username As String, ByVal Password As String) As String SendMailBPOS = "" Try Dim service As New ExchangeService(ExchangeVersion.Exchange2007_SP1) service.Url = New Uri(WebServiceURL) service.Credentials = New System.Net.NetworkCredential(Username, Password) Dim objMail As EmailMessage = New EmailMessage(service) objMail.From = New EmailAddress(MailFrom) If MailTo <> "" Then objMail.ToRecipients.Add(MailTo) End If If Cc <> "" Then objMail.CcRecipients.Add(Cc) End If If Bcc <> "" Then objMail.BccRecipients.Add(Bcc) End If If ReplyTo <> String.Empty Then objMail.ReplyTo.Add(New EmailAddress(ReplyTo)) Select Case Priority Case MailPriority.High : objMail.Importance = Importance.High Case MailPriority.Low : objMail.Importance = Importance.Low Case Else : objMail.Importance = Importance.Normal End Select
objMail.Subject = HtmlUtils.StripWhiteSpace(Subject, True)
objMail.Body = New MessageBody(CType(IIf(BodyFormat = MailFormat.Html, BodyType.HTML, BodyType.Text), BodyType), Body)
If Attachments.Count > 0 Then
objMail.Save()
' Add Attachments, converting from MailAttachments to Exchange Attachements
For Each myAtt As Attachment In Attachments
Dim mFilename As String = IO.Path.GetTempFileName()
Using fStream As New IO.FileStream(mFilename, IO.FileMode.OpenOrCreate)
Dim bArray As Byte()
ReDim bArray(CInt(myAtt.ContentStream.Length))
myAtt.ContentStream.Read(bArray, 0, CInt(myAtt.ContentStream.Length))
fStream.Write(bArray, 0, bArray.Length)
fStream.Close()
End Using
objMail.Attachments.AddFileAttachment(mFilename).Name = myAtt.Name
' It's is necessary to call .Save() in order to upload the attachment to the server
objMail.Save()
Next
End If
' send the message
objMail.SendAndSaveCopy()
Catch objException As Exception
' mail configuration problem
If Not IsNothing(objException.InnerException) Then
SendMailBPOS = String.Concat(objException.Message, ControlChars.CrLf, objException.InnerException.Message)
LogException(objException.InnerException)
Else
SendMailBPOS = objException.Message
LogException(objException)
End If
End TryEnd Function
Añadir posibilidad de configuración
Ahora toca modificar el interfaz de usuario para agregar soporte de configuración a los superusuarios del portal. Para ello, realizamos los pasos siguientes.
1. Abrir el archivo ~DesktopModulesAdminHostSettingshostsettings.ascx y buscamos en el marcado la tabla “tblSMTP”
2. Modificamos el marcado para agregar la posibilidad de indicar el tipo de servidor. También modificamos las etiquetas “tr” correspondientes a la autenticación y SSL para poder mostrarlas y ocultarlas desde el código de servidor.
<tr> <td class="SubHead" style="width: 250px"> <dnn:Label ID="plMailServerType" Text="Server type:" ControlName="cboMailServerType" runat="server" /> </td> <td align="left"> <asp:DropDownList ID="cboMailServerType" runat="server" AutoPostBack="true"> <asp:ListItem Value="SMTP" resourceKey="MailServerTypeSMTP">Servidor SMTP</asp:ListItem> <asp:ListItem Value="BPOS" resourceKey="MailServerTypeBPOS">Exchange Online</asp:ListItem> </asp:DropDownList> </td> </tr>
3. Agregamos las entradas correspondientes en los archivos .resx de recursos en la subcarpeta App_LocalResources
4. Modificamos la rutina ShowHideSMTPCredentials() y agregamos código en el evento de selección de la lista para mostrar/ocultar parámetros según esté seleccionado el tipo de servidor.
Private Sub ShowHideSMTPCredentials() If optSMTPAuthentication.SelectedValue = "1" OrElse cboMailServerType.SelectedValue = "BPOS" Then trSMTPPassword.Visible = True trSMTPUserName.Visible = True Else trSMTPPassword.Visible = False trSMTPUserName.Visible = False End If rowSMTPAthentication.Visible = cboMailServerType.SelectedValue = "SMTP" rowSMTPEnableSSL.Visible = rowSMTPAthentication.Visible End Sub
''' <summary> ''' Fires when the Mail server type dropdownlist changes ''' </summary> Protected Sub cboMailServerType_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles cboMailServerType.SelectedIndexChanged Try ShowHideSMTPCredentials() Catch ex As Exception ProcessModuleLoadException(Me, ex) End Try End Sub
5. Modificamos la rutina BindData() para volcar la propiedad configurada en el dropdown
'... cboMailServerType.SelectedValue = Entities.Host.Host.MailServerType.ToString() ShowHideSMTPCredentials() '...
6. Modificamos el evento cmdUpdate_Click para guardar el dato:
HostController.Instance.Update("MailServerType", [Enum].Parse(GetType(MailServerType), cboMailServerType.SelectedValue), False)
7. Con esto podemos configurar tanto el servidor SMTP como el servidor BPOS según nos convenga:
Al pulsar sobre el enlace “Probar” que trae incorporado DNN, realiza un envío de mensaje de prueba, que como podemos observar procesa correctamente nuestro Exchange Online.
Conclusión
En este artículo hemos visto la posibilidad de realizar envíos de correos desde DNN a través de Exchange Online. Para ello hemos utilizado la EWS Managed API 1.1, que facilita el manejo de los servicios web expuestos por Exchange.
Si en este ejemplo lo que hemos visto es cómo realizar los envíos a través de estos servicios, los servicios que ofrece la API son numerosos pudiéndose realizar casi cualquier cosa.
¿Cuándo comenzaremos a ver módulos desarrollados para explotar las características de Exchange desde nuestro portal DNN? Voy a ver si veo alguno por SnowCovered
Espero que os haya servidor de ayuda.
Un saludo y happy coding!
Bravo, siga así con más de Exchange Online y DontNetNuke !!! Salu2