I've written code that will find a specific email based on filtered criteria and then forward it to a new email address that gets passed into the code as a variable. It works perfectly, though the use case is to have it come from a generic email address, such as [email protected] (replacing example with our actual enterprise domain). I've tried to add a From element to the step that builds the requestBody that gets posted, but keep getting an error. I've researched online and read the MS guides on Graph, but have been unable to find a solution.
My code looks like this:
public async Task EmailForward(string notifNum, string forwardTo)
{
try
{
Console.WriteLine("Find and forward email - AMS notification " + notifNum);
string[] scopes = new[] { "https://graph.microsoft.com/.default" };
var tenantId = ConfigurationManager.AppSettings["tenantID"];
var clientId = ConfigurationManager.AppSettings["clientId"];
var clientSecret = ConfigurationManager.AppSettings["clientSecret"];
var options = new TokenCredentialOptions
{
AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
};
var clientSecretCredential = new ClientSecretCredential(tenantId, clientId, clientSecret, options);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
// Generates the user request builder
var userRequestBuilder = graphClient.Users["redacted-user-data"];
var sharedInbox = await userRequestBuilder.MailFolders["Inbox"].GetAsync();
//We need to first parse the notifNum to a number, then reconvert it to String so we can force the padding to always be exactly 12 digits
//So, let's start with defining the variable we'll eventually use to hold the properly formatted number along with the bit that precedes it in the subject line
string notifFormatted = "";
//Let's convert our notification number from a string to Int32
Int32 notifNumeric = 0;
if (Int32.TryParse(notifNum, out notifNumeric))
{
notifFormatted = "Notf# " + notifNumeric.ToString("000000000000");
}
//Setup filter so that it looks for the notification AND only from the us.ams email account (to prevent hits from [email protected] on failed delivery
//of emails for the same notification, potentially to a bad email address the first time, which may be triggering the request to forward in the first place.
string filterString = "contains(subject, '" + notifFormatted + "')AND startswith(from/emailAddress/address, '[email protected]')";
//Find the one (1) email that has the notification number in the subject line
var emlID = await userRequestBuilder.MailFolders["Inbox"].Messages.GetAsync(x =>
{
x.QueryParameters.Top = 1; //We have a filter in place to make sure it is only from [email protected], but still only want 1 email to be forwarded
x.QueryParameters.Filter = filterString;
});
if (emlID.Value.Count==0)
{
//No email matching the notification number in the filter was found...we need to report back and not attempt to forward since there's nothing to forward
Console.WriteLine("!!!No email found for notification " + notifNumeric + ". Skipping this notification!");
exitCode = 2;
return;
}
Console.WriteLine("Found email for subject line: " + notifFormatted);
string emlToFwd = emlID.Value[0].Id;
////Build up the needed setup to forward the message as "requestBody" to a different recipient
var requestBody = new Microsoft.Graph.Users.Item.Messages.Item.CreateForward.CreateForwardPostRequestBody
{
ToRecipients = new List<Recipient>
{
new Recipient
{
EmailAddress = new EmailAddress
{
Address = forwardTo,
},
},
},
};
var result = await userRequestBuilder.Messages[emlToFwd].CreateForward.PostAsync(requestBody);
await userRequestBuilder.Messages[result.Id].Send.PostAsync();
Console.WriteLine("Email forwarded to " + forwardTo + " for notification " + notifFormatted);
exitCode = 0;
}
catch (Exception ex)
{
Console.WriteLine(ex);
exitCode = 1;
}
}
I've tried adding something like the following after the close of the ToRecipients block:
From = new Recipient { EmailAddress = new EmailAddress { Address = "[email protected]"} }
But, I get the error that 'CreateForwardPostRequestBody' does not contain a definition for 'From'.
I haven't been able to find in the Graph documentation how to build the requestBody to include a different email address from which to forward the email. How do I get it to forward from a generic email like [email protected] instead of the actual mailbox/user executing the code via the credential flow?
You need to override the From part of the Message so the From address should be included with the Message Class of the forward eg this should work okay
The Address rules that apply when sending the Message are the same as those outlined in https://learn.microsoft.com/en-us/graph/outlook-send-mail-from-other-user so that address must exists (eg be assigned to a Mailbox) and you need permissions to SendAs that address. In the instance where your using client Credentials flow your impersonating the mailbox you have in graphServiceClient.Users which means that user must have SendAs permission to that address you trying to send as (even though you app maybe able to send a normal message from that address which in that instance its impersonating that mailbox)