none
Sending an Email Through C# RRS feed

  • Question

  • I am sure this is due to scope - but I'm not certain on how to remedy my issue. What my desired output is to have two emails generated. One saved for redfern1@test.com; hottomales2@gmail.com
    and a second email saved for: redfern2@test.com; hottomales4@gmail.com - Altho, what I'm getting is two emails 
    addressed to all of the emails.

    using System;
    using System.Data;
    
    public class Program
    {
    private static DataTable table = new DataTable();
    public static void Main()
    {
    table.Columns.Add("Company", typeof(string));
    table.Columns.Add("ContactEmails", typeof(string));
    table.Columns.Add("Month", typeof(string));
    table.Rows.Add("Company1", "redfern1@test.com; hottomales2@gmail.com", "March");
    table.Rows.Add("Company2", "redfern2@test.com; hottomales4@gmail.com", "March");
    
    foreach (DataRow r in table.Rows)
    if (r["Month"].ToString() == DateTime.Now.ToString("MMMM"))
    CreateEmail();
    }
    
    public static void CreateEmail()
    {
    Microsoft.Office.Interop.Outlook.Application aApp = new Microsoft.Office.Interop.Outlook.Application();
    Microsoft.Office.Interop.Outlook.MailItem oMsg = (Microsoft.Office.Interop.Outlook.MailItem)oApp.CreateItem(Microsoft.Office.Interop.Outlook.OlItemType.olMailItem);
    
    Microsoft.Office.Interop.Outlook.Recipients oRecips = (Microsoft.Office.Interop.Outlook.Recipients)oMsg.Recipients;
    
    foreach (DataRow r in table.Rows)
    {
    if (r["Month"].ToString() == DateTime.Now.ToString("MMMM"))
    {
    string email = r["ContactsEmail"].ToString();
    Microsoft.Office.Interop.Outlook.Recipient oRecip = (Microsoft.Office.Interop.Outlook.Recipient)oRecips.Add(email);
    oRecip.Resolve();
    }
    }
    
    oMsg.Save();
    }
    }

    Friday, March 15, 2019 3:25 PM

Answers

  • Take a look at the code I posted. Notice in the foreach loop I created a brand new message (msg) each time. You must do this otherwise you're simply adding to the message that you already had. It is this message (created each time through the loop) that has the recipients appended and therefore would only go to those recipients.

    Your final 2 lines where you're setting variables to null tell me you have created fields for the application and message. Don't do this. The COM objects are created and live only inside this method. Remove any references to them elsewhere.


    Michael Taylor http://www.michaeltaylorp3.net

    • Marked as answer by IndigoMontoya Friday, March 15, 2019 5:56 PM
    Friday, March 15, 2019 5:49 PM
    Moderator

All replies

  • Since each row represents an email you want to send you need to send it at the end of each foreach iteration. Because you're sending separate messages (one per row) you'll need separate items in each case. Move your message creation and adding of the recipients inside the loop and then call Save before the end.

    Note that I'm using the 16.0 object model as a test bed. I haven't tested this code at all. I also avoided making any adjustments to your logic beyond those needed to get the code to work. I did add a using statement for `Microsoft.Office.Interop.Outlook` at the top of the file to avoid having to use fully qualified names.

    static void CreateEmails ( DataTable table )
    {
        var app = new Application();
    
        var currentMonth = DateTime.Now.ToString("MMMM");
    
        foreach (DataRow row in table.Rows)
        {
            //Don't send if...
            if (row.Field<string>("Month") != currentMonth)
                continue;
    
            //Create a new message
            MailItem msg = app.CreateItem(OlItemType.olMailItem);
            msg.Recipients.Add(row.Field<string>("ContactsEmail"));
            msg.Recipients.ResolveAll();
    
            msg.Save();
        };
    }


    Michael Taylor http://www.michaeltaylorp3.net

    Friday, March 15, 2019 4:24 PM
    Moderator
  • Just for my further understanding - I should keep table as a class variable and keep my Main() method coded as is. Just make the change to the logic in the CreateEmails() method of checking if it is current month?

    I tested the code above and i'm still having each email address added to ONE email, instead of two emails saved for each row.

    Friday, March 15, 2019 4:43 PM
  • Sure, if that is how you have it now. I just passed the table into the function because I was using a sample console app.

    Looking at your code I see a couple of discrepancies. Firstly your sample table building code is using `ContactEmails` but in the code where you retrieve the emails you are using `ContactsEmail`. I assume this is a typo because you wouldn't be getting anything otherwise.

    Secondly I looked at the docs for Recipients.Add. It doesn't mention supporting multiple emails in a single call so you'll need to break up add logic to account for multiple emails. Maybe something along these lines.

    var emails = row.Field<string>("ContactsEmail").Split(';');
    foreach (var email in emails)
       msg.Recipients.Add(email);
    msg.Recipients.ResolveAll();


    Michael Taylor http://www.michaeltaylorp3.net


    Friday, March 15, 2019 5:23 PM
    Moderator
  • Yeah - that was a typo - my mistake.

    If I try the code above - on the Recipients.Add(email); line I get a compile error of

    Argument 1: cannot convert from char to string

    Friday, March 15, 2019 5:30 PM
  • Sorry, forgot the call to actually split the string. Updated the code. Try again.

    Michael Taylor http://www.michaeltaylorp3.net

    Friday, March 15, 2019 5:36 PM
    Moderator
  • THis is the code I currently have, and I have a breakpoint set on oMsg = null - but I am still getting an email with all of the email addresses. 

    static void CreateEmails ()
    {
        var app = new Application();
    
        var currentMonth = DateTime.Now.ToString("MMMM");
    
        foreach (DataRow row in table.Rows)
        {
            if (row.Field<string>("Month") != currentMonth)
                continue;
    
    		var emails = row.Field<string>("ContactsEmail").Split(';');
    		foreach (var email in emails)
    			msg.Recipients.Add(email);
    		msg.Recipients.ResolveAll();
    
            msg.Save();
        };
    	
    	oMsg = null;
    	oApp = null;
    }

    Friday, March 15, 2019 5:45 PM
  • Take a look at the code I posted. Notice in the foreach loop I created a brand new message (msg) each time. You must do this otherwise you're simply adding to the message that you already had. It is this message (created each time through the loop) that has the recipients appended and therefore would only go to those recipients.

    Your final 2 lines where you're setting variables to null tell me you have created fields for the application and message. Don't do this. The COM objects are created and live only inside this method. Remove any references to them elsewhere.


    Michael Taylor http://www.michaeltaylorp3.net

    • Marked as answer by IndigoMontoya Friday, March 15, 2019 5:56 PM
    Friday, March 15, 2019 5:49 PM
    Moderator