• Microsoft LightSwitch – Sending Emails From the Client

    Posted May 26th, 2011 By in ForFeedOne, LightSwitch With| 13 Comments | Microsoft LightSwitch – Sending Emails From the Client
    Share on TwitterSubmit to StumbleUponSave on DeliciousDigg ThisSubmit to reddit

    Most of you may have already read an earlier post on how to send emails from LightSwitch (seen here). This post extends what was learned in that previous post, and shows how to wire up a button to send an email on demand.That previous post showed a specific function that would send out an email when an entity was added to the database. A helper class was created in the Server project of the LightSwitch solution. Then, when the new record was created in the database, that server code was called and an email went out.

    The whole process was pretty simple to implement, however it was a good exercise that helped me better understand how LightSwitch separates concerns. It was this knowledge and understanding that helped me implement a solution for another email challenge.

    The challenge I have is this; I want functionality that will let me send an email on demand, via a button on a screen, and I don’t want to code some fancy WCF service or custom extension to do the job.

    Here is the thing – you can’t call server code from the client. It is in the server code that the email processing occurs. Why? Because the client and common projects are Silverlight based projects and I can’t add the necessary System.Net reference to those projects – otherwise I would have used the System.Net.Mail namespace directly from the client.

    But hey, the Server project is a .Net 4 class library project, and I can add the System.Net reference to that project. That is why the actual email processing has to occur in the Server project. Following me so far?

    So, here is what I did…

    For the sake of this post and your reference, I created a simple project named “SendEmail”.

    In the Solution Explorer of my LightSwitch project, I switched to File View so that I can get at the Server project…

    Knowing that I need to use an external (SMTP) email service to actually send out the email, I decided to store some static information that my email processing can use to process the email; such as stuff for the email service authentication. To do this, I opened the Server project settings.

    Next, I added some Application scoped configuration settings…

    …come on, you didn’t actually think that I would post my own credentials did ya…I learned from that mistake already :)

    I made sure to save the updates.

    Next, a folder is created within the Server project, and named the folder “UserCode”. Within that folder I created a new Class file and named it “EmailHelper.vb”.

    This is the code I added to this file…

    Imports System.Net
    Imports System.Net.Mail
    
    Namespace LightSwitchApplication
        Public Class MailHelper
    
            Private Property SMTPServer As String = My.Settings.SMTPServer
            Private Property SMTPUserId As String = My.Settings.SMTPUserID
            Private Property SMTPPassword As String = My.Settings.SMTPPassword
            Private Property SMTPPort As Integer = My.Settings.SMTPPort
    
            Private Property MailFrom As String
            Private Property MailFromName As String
            Private Property MailTo As String
            Private Property MailToName As String
            Private Property MailSubject As String
            Private Property MailBody As String
    
            Sub New(ByVal SendFrom As String,
                    ByVal SendFromName As String, _
                    ByVal SendTo As String, _
                    ByVal SendToName As String, _
                    ByVal Subject As String, _
                    ByVal Body As String)
                _MailFrom = SendFrom
                _MailFromName = SendFromName
                _MailTo = SendTo
                _MailToName = SendToName
                _MailSubject = Subject
                _MailBody = Body
            End Sub
    
            Public Sub SendMail()
    
                Dim SMTPUserAddress = New MailAddress(_SMTPUserId)
    
                Dim mail As New MailMessage
                Dim mailFrom As New Mail.MailAddress(_MailFrom, _MailFromName)
                Dim mailTo As New Mail.MailAddress(_MailTo, _MailToName)
    
                With mail
                    .From = mailFrom
                    .To.Add(mailTo)
                    .Subject = _MailSubject
                    .Body = _MailBody
                End With
    
                Dim smtp As New SmtpClient(_SMTPServer, _SMTPPort)
                smtp.EnableSsl = True
    
                smtp.Credentials = New NetworkCredential(SMTPUserAddress.Address, _SMTPPassword)
                smtp.Send(mail)
            End Sub
    
        End Class
    End Namespace

    So, this class contains some pretty simple code. Instantiating the class requires a bunch of parameters that are later used by the SendMail() method. The SendMail() methid is where the mail message gets created, configured, and sent using the a SmtpClient. As you can see, some class properties are defaulted to the values that are stored in the App.Config file of the Server project (which were added earlier).

    Next, I go back into the logical view of the solution.

    In the logical view, a new table is created. The table name is “ProxyEmail”, and it looks like this…

    Now, with this table, I have essentially created a “Model” that I can use in my workaround. Remember, my challenge is to do all this with native LightSwitch features and functionality. I don’t want to create a fancy-smancy WCF service or custom extension for this. I just want to get the job done. By creating this entity, I have, in essence, created a business object that I am going to use to do what I want to do.

    Here is the fun part! I can’t call the Server code directly from any screens, however I know that my “entity” can access the server code via its dependencies. For example, my ProxyEmail entity has a method called ProxyEmails_Inserted(), which runs on the server when an entity as added to the table (add to the collection of ProxyEmail entities).

    So, I add some code to this method…

    …and here is the code if you want…

     Private Sub ProxyEmails_Inserted(entity As ProxyEmail)
                ' Write your code here.
                Dim sSubject = "Test Email."
                Dim carRtn = Environment.NewLine & Environment.NewLine
    
                Dim sMessage = "The following email has come from a button on LightSwitch..." & carRtn
                sMessage += "Testing 1, 2, 3!!"
    
                ' Create the MailHelper class created in the Server project.
                Dim mailHelper As New MailHelper(entity.SenderEmailAddress, _
                                                 entity.RecipientName, _
                                                 entity.RecipientEmailAddress, _
                                                 entity.RecipientName, _
                                                 sSubject, _
                                                 sMessage)
    
                ' Let 'er rip!
                mailHelper.SendMail()
            End Sub

    So, this is pretty much the same as the last post. Right, but here is how this similar stuff is used to create a feature that will allow you to send an email on demand, rather than relying only on updates to entities.

    I create a new Screen and, using the New Data Screen template, name it “SendAnEmail”, but don’t assign any screen data to it…

    In the screen designer for the new SendAnEmail screen, I click Add Data Item… and create a Method with a name of “SendMyEmailOnDemand”…

    Back in the screen designer, I expand the Screen Command Bar, and drag and drop the SendMyEmailOnCommand method to the command bar.

    I right click the newly added button, and select to Edit Execute Code.

    I edit the method to this…

    …and here is the actual code you can use…

            Private Sub SendEmailOnCommand_Execute()
                Dim newEmail = DataWorkspace.ApplicationData.ProxyEmails.AddNew()
                With newEmail
                    .RecipientEmailAddress = "paulspatterson@hotmail.com"
                    .RecipientName = "Paul Patterson"
                    .SenderEmailAddress = "paul@selectsystems.ca"
                    .SenderName = "Paul Patterson (Select Systems)"
                End With
    
                DataWorkspace.ApplicationData.SaveChanges()
                newEmail.Delete()
                DataWorkspace.ApplicationData.SaveChanges()
            End Sub

    What this is doing is simply creating a new ProxyEmail entity, settings it’s properties, the committing the insert to the system. The SaveChanges after the setting the properties will cause the ProxyEmails collection to fire that ProxyEmails_Inserted() method that was wired up earlier, which then sends the email from the server code. After that, the newly added entity is deleted because I don’t need it any more.

    So, I F5 to test it…

    … and I click the Send Email On Demand button. Then I go and check my email, and presto…

    Yes!

    This may not be the super cool software code monkey way of doing things, but who cares! It does the job, and I did in no time at all.

    Hope you find it useful!

    Cheers


    • delicious
    • digg
    • reddit

    Paul
    My name is Paul Patterson and I am a software developer who has a keen interest in technology, including; open source, .Net, and anything Interweb. When not crafting some code, I can be found learning something new about photography. As well, I occasionally escape to the "music room" with my guitars to practice a few scales and then jam with my favourite FM radio stations.

Leave a Reply


Comments (13)

Reply
adefwebserver » 26. May, 2011

Woderful!

Reply
Teranga » 02. Jul, 2011

Génial !!!!!!

Reply
PaulSPatterson » 03. Jul, 2011

Thank you…, À votre bon cœur !

Reply
Rafal » 29. Jul, 2011

Awesome stuff and a great blog. I've been using LightSwitch for a day (c# for few years) and this is just amazing to start off with. Too bad it's all VB.NET, but you can't have it all in life. I get it 100%, but it just looks awkward to me lol.

Reply
Peter » 26. Aug, 2011

This is good One.

Reply
Ranjan » 03. Sep, 2011

Hi Paul

Do you have any idea regarding, how to send attachment (e.g .pdf, .doc, etc) through email from lightswitch application.

Reply
PaulSPatterson » 08. Sep, 2011

Hmm. Good question.

I believe that an attachment can be included by adding it as an Attachment object (see here: http://msdn.microsoft.com/en-us/library/system.ne

Reply
Francis Lebel » 06. Jan, 2012

This is exactly what I was looking for. Many Thanks Paul !!

Reply
PaulSPatterson » 09. Jan, 2012

Glad this helped Francis.

Good to see that this article is still relevant today. Let us know how it works out.

Paul

Reply
Bhuven » 10. Jan, 2012

This is great, thank you Is this available in C#

Reply
Justin Halls » 07. Mar, 2012

That is great and I have it working beautifully. However, I now have a slightly different related problem – maybe somone has some neat ideas? I want to send out a bulk emailing, so I modify the entity parameters to say what is needed and the server side code extracts all the relevant data from the database formats it and sends it. In order to return control I do all the collation and sending in a new thread. But then I need to be able to alert my user if one or more of the emails has failed – so how to get that information back to them. I had planned to add a status to a special table in the databse sothat there would also be a permanent record of every emailing and whether ot not it succeeded, BUT I cannot do a savechanges() on the databse from code started from the inserted() function as that original savechanges() is still in progress.
Any neat ideas?
please?

Reply
PaulSPatterson » 07. Mar, 2012

Hi Justin,

Leveraging a custom table for the status of the bulk email process is a great idea. I'll try a couple of ideas to see what might work for you. I'll keep you in the loop.

Paul

Reply
Robert Lewis » 30. Mar, 2012

This has been very helpful. Thank you!!

© Copyright Paul S Patterson - Please, no touchie. :)