There was an error in this gadget

Tuesday, 4 May 2010

Emailing the contents of a Devexpress RichEditControl (with embedded images)

Following on from my previous post about emailing an XtraReport.  This is a short extension method to allow the same thing for a RichEditControl.
1. Add this module to your project.
Imports DevExpress.XtraRichEdit
Imports System.Runtime.CompilerServices
Imports System.Net.Mail

Module RTFExtension

<Extension()>
Public Function GetMailMessage(ByVal RTF As RichEditControl) As MailMessage
' Create a holder for the images in the RichEditControl
Dim Images As New List(Of LinkedResource)

' Get the HTML. We pass in out Custom URI provider to convert the image URL's into a format we can use
Dim MailBody = RTF.Document.GetHtmlText(RTF.Document.Range, New EmailUriProvider(Images))

' Create the HTML view
Dim HTML = AlternateView.CreateAlternateViewFromString(MailBody, Nothing, "text/html")

' Add the images to the view
Images.ForEach(AddressOf HTML.LinkedResources.Add)

' Create the new mail message and add the view to it
Dim MM As New MailMessage()
MM.AlternateViews.Add(HTML)

Return MM
End Function

End Module

2. Add this class
Imports DevExpress.XtraRichEdit.Services
Imports System.Net.Mail

Friend Class EmailUriProvider
Implements IUriProvider

Private _Images As List(Of LinkedResource)

Public Sub New(ByRef Images As List(Of LinkedResource))
_Images = Images
End Sub

Public Function CreateCssUri(ByVal rootUri As String, ByVal styleText As String, ByVal relativeUri As String) As String Implements IUriProvider.CreateCssUri
' We are not processing CSS files
Throw New NotImplementedException
End Function

Public Function CreateImageUri(ByVal rootUri As String, ByVal image As System.Drawing.Image, ByVal relativeUri As String) As String Implements DevExpress.XtraRichEdit.Services.IUriProvider.CreateImageUri

' Create a 
Dim G = Guid.NewGuid

Dim MS = New IO.MemoryStream
image.Save(MS, Drawing.Imaging.ImageFormat.Png)
MS.Position = 0

' Create an embedded image from the memorystream 
Dim R As New LinkedResource(MS, "image/png")

' Set the image identifier to the Value we want to appear in the HTML    
R.ContentId = String.Format("img{0}", G.ToString)

_Images.Add(R)

Return String.Format("cid:img{0}", G)
End Function
End Class



3. Then it’s just a simple case of using the following code to convert the contents of a RichEditControl into a MailMessage you can send.
Dim MM As System.Net.Mail.MailMessage = MyRichEditControl.GetMailMessage()

Job done. :-)


UPDATE: Devexpress changed the signature of the interface. From version 10.2 onwards the CreateImageUri method should be (Changes in Red):
Public Function CreateImageUri(ByVal rootUri As String, ByVal image As DevExpress.XtraRichEdit.Utils.RichEditImage, ByVal relativeUri As String) As String Implements DevExpress.XtraRichEdit.Services.IUriProvider.CreateImageUri
' Create a 
Dim G = Guid.NewGuid

Dim MS = New IO.MemoryStream
image.Save(MS, Drawing.Imaging.ImageFormat.Png) 
Dim B = image.GetImageBytes(DevExpress.XtraRichEdit.Utils.RichEditImageFormat.Png)
MS.Write(B, 0, B.Length)
MS.Position = 0 ' Create an embedded image from the memorystream Dim R As New LinkedResource(MS, "image/png") ' Set the image identifier to the Value we want to appear in the HTML R.ContentId = String.Format("img{0}", G.ToString) _Images.Add(R) Return String.Format("cid:img{0}", G) End Function