diff --git a/.gitignore b/.gitignore index c0628e8..0de0229 100644 --- a/.gitignore +++ b/.gitignore @@ -242,4 +242,7 @@ ModelManifest.xml .fake/ # Autogenerated XML documentation file -Frends.Community.*/Frends.Community.*/Frends.Community.*.xml \ No newline at end of file +Frends.Community.*/Frends.Community.*/Frends.Community.*.xml + +# Run settings containing secret environment variables +/.runsettings diff --git a/Frends.Community.Email.Tests/ReadExchangeEmailTests.cs b/Frends.Community.Email.Tests/ReadExchangeEmailTests.cs index 10965ab..027bc33 100644 --- a/Frends.Community.Email.Tests/ReadExchangeEmailTests.cs +++ b/Frends.Community.Email.Tests/ReadExchangeEmailTests.cs @@ -15,7 +15,8 @@ namespace Frends.Community.Email.Tests public class ReadExchangeEmailTests { private readonly string _mailfolder = "Inbox"; - private readonly string _username = "frends_exchange_test_user@frends.com"; + private readonly string _username = Environment.GetEnvironmentVariable("Exchange_User") ?? "frends_exchange_test_user@frends.com"; + private readonly string _otherUser = Environment.GetEnvironmentVariable("Exchange_Other_User") ?? "frends_exchange_test_user_2@frends.com"; private readonly string _password = Environment.GetEnvironmentVariable("Exchange_User_Password"); private readonly string _applicationID = Environment.GetEnvironmentVariable("Exchange_Application_ID"); private readonly string _tenantID = Environment.GetEnvironmentVariable("Exchange_Tenant_ID"); @@ -312,7 +313,7 @@ public async Task ItemAttachmentWillNotFailTask() public async Task ReadOtherUsersInbox() { var subject = "Read From Other User"; - await SendTestEmail(subject, "frends_exchange_test_user_2@frends.com"); + await SendTestEmail(subject, _otherUser); var options = new ExchangeOptions { MaxEmails = 1, @@ -330,12 +331,12 @@ public async Task ReadOtherUsersInbox() Username = _username, Password = _password, MailFolder = _mailfolder, - Mailbox = "frends_exchange_test_user_2@frends.com" + Mailbox = _otherUser }; var result = await ReadEmailTask.ReadEmailFromExchangeServer(settings, options, new CancellationToken()); Assert.AreEqual(1, result.Count); - await DeleteMessages(subject, "frends_exchange_test_user_2@frends.com"); + await DeleteMessages(subject, _otherUser); } [Test] @@ -343,7 +344,7 @@ public async Task ReadAttachmentFromOtherUsersInbox() { var subject = "Read Attachment From Other User"; var dirPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "../../../OtherUserAttachment/"); - await SendTestEmailWithAttachment(subject, "OtherUserAttachment.txt", "frends_exchange_test_user_2@frends.com"); + await SendTestEmailWithAttachment(subject, "OtherUserAttachment.txt", _otherUser); var options = new ExchangeOptions { MaxEmails = 1, @@ -363,13 +364,13 @@ public async Task ReadAttachmentFromOtherUsersInbox() Username = _username, Password = _password, MailFolder = _mailfolder, - Mailbox = "frends_exchange_test_user_2@frends.com" + Mailbox = _otherUser }; var result = await ReadEmailTask.ReadEmailFromExchangeServer(settings, options, new CancellationToken()); Assert.IsTrue(File.Exists(result[0].AttachmentSaveDirs[0])); Directory.Delete(dirPath, true); - await DeleteMessages(subject, "frends_exchange_test_user_2@frends.com"); + await DeleteMessages(subject, _otherUser); } [Test] diff --git a/Frends.Community.Email.Tests/SendExchangeEmailTests.cs b/Frends.Community.Email.Tests/SendExchangeEmailTests.cs index 6e21b7a..aabfa1d 100644 --- a/Frends.Community.Email.Tests/SendExchangeEmailTests.cs +++ b/Frends.Community.Email.Tests/SendExchangeEmailTests.cs @@ -14,7 +14,8 @@ namespace Frends.Community.Email.Tests [TestFixture] public class SendExchangeEmailTests { - private readonly string _username = "frends_exchange_test_user@frends.com"; + private readonly string _username = Environment.GetEnvironmentVariable("Exchange_User") ?? "frends_exchange_test_user@frends.com"; + private readonly string _otherUser = Environment.GetEnvironmentVariable("Exchange_Other_User") ?? "frends_exchange_test_user_2@frends.com"; private readonly string _password = Environment.GetEnvironmentVariable("Exchange_User_Password"); private readonly string _applicationID = Environment.GetEnvironmentVariable("Exchange_Application_ID"); private readonly string _tenantID = Environment.GetEnvironmentVariable("Exchange_Tenant_ID"); @@ -49,7 +50,7 @@ public async Task SendEmailWithPlainTextTest() To = _username, Message = message, IsMessageHtml = false, - Subject = subject + Subject = subject, }; var result = await EmailTask.SendEmailToExchangeServer(input, null, _server, new CancellationToken()); @@ -339,7 +340,7 @@ public async Task SendEmailAsAnotherUserTest() var input = new ExchangeInput { To = _username, - From = "frends_exchange_test_user_2@frends.com", + From = _otherUser, Message = message, IsMessageHtml = false, Subject = subject @@ -349,7 +350,45 @@ public async Task SendEmailAsAnotherUserTest() Assert.IsTrue(result.EmailSent); Thread.Sleep(2000); // Give the email some time to get through. var email = await ReadTestEmail(subject); - Assert.AreEqual("frends_exchange_test_user_2@frends.com", email[0].From); + Assert.AreEqual(_otherUser, email[0].From); + await DeleteMessages(subject); + } + + [Test] + public async Task SendEmailAsAnotherUserWithStringAttachmentTest() + { + var filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "../../../stringAttachmentFile.txt"); + var subject = "Email test - AnotherUserStringAttachment"; + var input = new ExchangeInput + { + To = _username, + From = _otherUser, + Message = "This email has an attachment written from a string.", + IsMessageHtml = false, + Subject = subject + }; + + var stringAttachment = new AttachmentFromString + { + FileContent = "This is a test attachment from string.", + FileName = "stringAttachmentFile.txt" + }; + + var attachment = new Attachment + { + AttachmentType = AttachmentType.AttachmentFromString, + StringAttachment = stringAttachment + }; + + var attachmentArray = new Attachment[] { attachment }; + + var result = await EmailTask.SendEmailToExchangeServer(input, attachmentArray, _server, new CancellationToken()); + Assert.IsTrue(result.EmailSent); + Thread.Sleep(2000); // Give the email some time to get through. + var email = await ReadTestEmailWithAttachment(subject); + Assert.AreEqual(_otherUser, email[0].From); + Assert.IsTrue(File.Exists(filePath)); + File.Delete(filePath); await DeleteMessages(subject); } diff --git a/Frends.Community.Email/EmailTask.cs b/Frends.Community.Email/EmailTask.cs index 0ea548c..ba62e53 100644 --- a/Frends.Community.Email/EmailTask.cs +++ b/Frends.Community.Email/EmailTask.cs @@ -166,6 +166,9 @@ public static async Task SendEmailToExchangeServer([PropertyTab] Exchang var to = new List(); var cc = new List(); var bcc = new List(); + Recipient from = null; + IUserRequestBuilder user; + foreach (var receiver in recipients) to.Add(new Recipient { EmailAddress = new EmailAddress { Address = receiver } }); @@ -179,54 +182,54 @@ public static async Task SendEmailToExchangeServer([PropertyTab] Exchang recipients = input.Bcc.Split(new char[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries); foreach (var receiver in recipients) bcc.Add(new Recipient { EmailAddress = new EmailAddress { Address = receiver } }); } - - if (attachments != null && attachments.Length > 0) + if (!string.IsNullOrWhiteSpace(input.From)) { - return await SendExchangeEmailWithAttachments(attachments, graph, input.Subject, messageBody, to, cc, bcc, cancellationToken); + from = new Recipient { EmailAddress = new EmailAddress { Address = input.From } }; + user = graph.Users[input.From]; } else { - var message = new Message - { - Subject = input.Subject, - Body = messageBody, - ToRecipients = to, - CcRecipients = cc, - BccRecipients = bcc - }; - if (string.IsNullOrWhiteSpace(input.From)) - await graph.Me.SendMail(message, true).Request().PostAsync(cancellationToken); - else - await graph.Users[input.From].SendMail(message, true).Request().PostAsync(cancellationToken); - return new Output - { - EmailSent = true, - StatusString = $"Email sent to: {input.To}" - }; + user = graph.Me; } - } - - #region HelperMethods - - private static async Task SendExchangeEmailWithAttachments(Attachment[] attachments, GraphServiceClient graphClient, string subject, ItemBody messageBody, List to, List cc, List bcc, CancellationToken cancellationToken) - { - var attachmentList = new MessageAttachmentsCollectionPage(); - var allAttachmentFilePaths = new List(); var message = new Message { - Subject = subject, + Subject = input.Subject, Body = messageBody, ToRecipients = to, CcRecipients = cc, - BccRecipients = bcc + BccRecipients = bcc, + From = from, }; - var msgResult = await graphClient.Me.Messages.Request().AddAsync(message, cancellationToken); + return await SendExchangeEmail(user, message, attachments, cancellationToken); + } - foreach (var attachment in attachments) + #region HelperMethods + + private static async Task SendExchangeEmail(IUserRequestBuilder user, Message message, Attachment[] attachments, CancellationToken cancellationToken) + { + var to = string.Join(", ", message.ToRecipients.Select(x => x.EmailAddress.Address)); + var successMessage = $"Email sent to: {to}"; + + // Short circuit if no attachments, SendMail requires less permissions than creating Messages + if (attachments == null || attachments.Length == 0) { + await user.SendMail(message, true).Request().PostAsync(cancellationToken); + return new Output + { + EmailSent = true, + StatusString = successMessage + }; + } + + var attachmentList = new MessageAttachmentsCollectionPage(); + var allAttachmentFilePaths = new List(); + + var msgResult = await user.Messages.Request().AddAsync(message, cancellationToken); + foreach (var attachment in attachments) + { string tempFilePath = ""; if (attachment.AttachmentType == AttachmentType.AttachmentFromString) { @@ -270,7 +273,7 @@ private static async Task SendExchangeEmailWithAttachments(Attachment[] Size = info.Length }; - var uploadSession = await graphClient.Me.Messages[msgResult.Id].Attachments.CreateUploadSession(attachmentItem).Request().PostAsync(cancellationToken); + var uploadSession = await user.Messages[msgResult.Id].Attachments.CreateUploadSession(attachmentItem).Request().PostAsync(cancellationToken); var allBytes = File.ReadAllBytes(filePath); using (var stream = new MemoryStream(allBytes)) @@ -284,11 +287,11 @@ private static async Task SendExchangeEmailWithAttachments(Attachment[] } } - await graphClient.Me.Messages[msgResult.Id].Send().Request().PostAsync(cancellationToken); + await user.Messages[msgResult.Id].Send().Request().PostAsync(cancellationToken); return new Output { EmailSent = true, - StatusString = $"Email sent to: {to}" + StatusString = successMessage }; }