We have a portal in our company and our users login using their corporate account that is synced with Azure AD. We want to show an indicator on our portal of their unread emails. Do I need to get all email and count the ones that are unread on can I filter on unread and get a count on the collection? Both solution will deliver high traffic so is there a more performance way?
The return value of a messages call with Graph also has the unreademail count in UnreadItemCount. Best way is to use the NUGET package Microsoft.Graph, make a call, cast the result to mailfolder and retrieve the unread email count:
HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
//Get 10 Unread Messages
Task<HttpResponseMessage> call = httpClient.GetAsync("https://graph.microsoft.com/v1.0/me/mailfolders/Inbox");
call.Wait();
var responseUnread = call.Result;
if (responseUnread.IsSuccessStatusCode)
{
string s = await responseUnread.Content.ReadAsStringAsync();
JavaScriptSerializer serializer = new JavaScriptSerializer();
//Deserialize to Microsoft.Graph.MailFolder NUGET:Microsoft.Graph
var mf = serializer.Deserialize<MailFolder>(s);
unreadMail = mf.UnreadItemCount;
}
Related
I am creating a batch job to read email from an inbox using Microsoft Graph API and publish the content of the email using service bus.
I put a duplicate detection in my azure service bus based on the assigned Message ID. To prevent publishing the same email, I put the Email message Id to the Azure Service Bus Message ID.
However it seems that the length of the email message ID is too long and I am unable to fit it as the azure service bus message ID. Any solution on how to put the email message ID as the Azure Service Bus message ID? (I am not allowed to store the email message ID in any persistence storage, I can only publish it via Azure Service Bus)
Thanks
The length of the service bus message ID can't exceed 128 characters. Generally, the value of
email ids that you retrieved from Microsoft Graph API look like:
AAMkADU1NzNkY2I2LWIxY2QtNGFhOC1iYmE5LWEzODA2ZjJkMjQxNwBGAAAAAABRRlt89urpT62rDl3o5R1RBwCSQ84srYEXTY2slhDtcrhrAAAAAAEMAACSQ84srYEXTY2slhDtcrhrAABlQp2FAAA=
Generally, its length is 188 characters which caused this issue.
To solve this issue, you can try to use MD5 to create a unified identifier for the email ID, by default, its length will be 32 characters, though this value has the possibility to collision with a hash that from a different string, but its possibility is low(about 2^-128).
If you are using C#, just try the code below:
using Azure.Messaging.ServiceBus;
using System;
using System.Security.Cryptography;
using System.Text;
namespace serviceBusTest
{
class Program
{
static void Main(string[] args)
{
string connectionString = "";
string queueName = "";
var client = new ServiceBusClient(connectionString);
ServiceBusSender sender = client.CreateSender(queueName);
ServiceBusMessage message = new ServiceBusMessage();
var emailID = "AAMkADU1NzNkY2I2LWIxY2QtNGFhOC1iYmE5LWEzODA2ZjJkMjQxNwBGAAAAAABRRlt89urpT62rDl3o5R1RBwCSQ84srYEXTY2slhDtcrhrAAAAAAEMAACSQ84srYEXTY2slhDtcrhrAABlQp2FAAA=";
message.MessageId = GetMd5Hash(MD5.Create(), emailID);
sender.SendMessageAsync(message).GetAwaiter().GetResult();
ServiceBusReceiver receiver = client.CreateReceiver(queueName);
ServiceBusReceivedMessage receivedMessage = receiver.ReceiveMessageAsync().GetAwaiter().GetResult();
Console.WriteLine(receivedMessage.MessageId);
}
static string GetMd5Hash(MD5 md5Hash, string input)
{
byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));
StringBuilder sBuilder = new StringBuilder();
for (int i = 0; i < data.Length; i++)
{
sBuilder.Append(data[i].ToString("x2"));
}
return sBuilder.ToString();
}
}
}
Result:
We have a stand alone process which needs to get call record details of completed calls via the Graph API.
We have obtained record IDs via the Azure Dashboard so that we can use them with the following endpoint
GET https://graph.microsoft.com/v1.0/communications/callRecords/{id}
as shown in
https://learn.microsoft.com/en-us/graph/api/callrecords-callrecord-get?view=graph-rest-1.0
The Azure App has been configured for access and has readAll permissions set.
The following code generates a token for access, but when actually trying to read back a call record specified by id, it always returns 404 Not found.
var scopes = new string[] { "https://graph.microsoft.com/.default" };
IConfidentialClientApplication app;
app = ConfidentialClientApplicationBuilder.Create(clientID)
.WithClientSecret(clientSecret)
.WithAuthority(new Uri(authority))
.Build();
var result = await app.AcquireTokenForClient(scopes).ExecuteAsync();
HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
string id = "YYYYYYYY-F571-45D9-ABC6-XXXXXXXXXXXX"; // Real ID, but obfuscated for this example
HttpResponseMessage response = await httpClient.GetAsync(new Uri("https://graph.microsoft.com/v1.0/communications/callRecords/" + id));
Can anyone advise what I am missing.
Thanks
Another company we partner with sends us new client information via DocuSign envelopes completed by those clients. I am attempting to extract the form data from the document, either via the PDF or via the DocuSign API. The PDF only appears to have the Envelope ID embedded in it. When I add my account as a CC recipient and try to view the form data in the DocuSign console, I receive an error message:
Additionally, I'm unable to view the form data via the DocuSign API.
{
errorCode: "USER_LACKS_PERMISSIONS",
message: "This user lacks sufficient permissions to access this resource."
}
I've tried accessing via the API at:
/v2/accounts/{accountId}/envelopes/{envelopeId}/recipients/{recipientId}/tabs
/v2/accounts/{accountId}/envelopes/{envelopeId}/documents/{documentId}/fields
Questions:
Is there a way for a user who is not in the sender's tenant to be able to view the envelope form data?
Is there a way for DocuSign to embed the tab data into the PDF for extraction?
Is there another approach I'm not considering?
If the user is cc to the envelope using the same userId and email combination that is on their account, then that user also can use the API to gain account information. (account is what you call "tenant.")
If the user is not on the envelope and you just receive the PDF some other way, then you cannot use the API to obtain information about the envelope because that is limited only to recipients of the envelope.
#Inbar-Gazit was kind enough to do some digging internally at DocuSign, and after a bit of back-and-forth, discovered that this is possible using the SOAP API with the RequestEnvelope and RequestEnvelopeV2 methods. I'm unsure if there's any advantage to using one method over the other. Both also have async methods.
https://developers.docusign.com/docs/esign-soap-api/reference/Status-and-Managing-Group/RequestEnvelope
Some quick-and-dirty C# validated that this will indeed work. I validated this both as the sending account (which also works via REST) and the CC recipient account (which did not work via REST).
var authString = $"<DocuSignCredentials><Username>{_userName}</Username><Password>{_password}</Password><IntegratorKey>{_apiKey}</IntegratorKey></DocuSignCredentials>";
var client = new DSAPIServiceSoapClient();
using (OperationContextScope scope = new OperationContextScope(client.InnerChannel))
{
HttpRequestMessageProperty httpRequestProperty = new HttpRequestMessageProperty();
httpRequestProperty.Headers.Add("X-DocuSign-Authentication", authString);
OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpRequestProperty;
EnvelopeStatus status = client.RequestStatusEx(_envelopeId);
Console.Out.WriteLine("Subject: " + status.Subject);
// RequestEnvelope Method
var envelope = client.RequestEnvelope(_envelopeId, false);
var testTab = envelope.Tabs.FirstOrDefault(t => t.TabLabel.Contains("Test"));
if (testTab != null)
{
Console.WriteLine($"Tab {testTab.TabLabel}: {testTab.Value}");
} else
{
Console.WriteLine("Tab not found.");
}
// RequestEnvelopeV2 Method
var requestOptions = new RequestEnvelopeV2Options() {
IncludeAC = false,
IncludeAnchorTabLocations = true,
IncludeDocumentBytes = false
};
var envelopeV2 = client.RequestEnvelopeV2(_envelopeId, requestOptions);
var testTabV2 = envelopeV2.Tabs.FirstOrDefault(t => t.TabLabel.Contains("Test"));
if (testTabV2 != null)
{
Console.WriteLine($"Tab(v2) {testTabV2.TabLabel}: {testTabV2.Value}");
} else
{
Console.WriteLine("Tab(v2) not found.");
}
Console.WriteLine("\r\nDone.");
Console.ReadKey();
}
Output:
Subject: Please DocuSign: Test Envelope
Tab txtDataLabelTest1: Some Data Here
Tab(v2) txtDataLabelTest1: Some Data Here
Done.
I'm trying to use SendGrid to send an email from an Azure worker role every time there are certain exceptions, but I can't get the email to send. I am using SendGridMail version 6.1.0.0 and SendGrid.SmtpApi version 1.3.1.0 which I installed via nuget and .Net 4.5. I am currently debugging locally with plans to deploy to Azure if i can get the emails to successfully send.
SendGridMessage myMessage = new SendGridMessage();
List<String> recipients = new List<String> { #"John Doe <johnd#outlook.com>", #"Peter Howe <perterhowe#gmail.com>" };
myMessage.AddTo(recipients);
myMessage.From = new MailAddress("myemail#test.com");
myMessage.Subject = "Error in Update";
myMessage.Text = "TESTING 123";
string username = XXXXXX;
string password = XXXXXXX;
// Create credentials, specifying your user name and password.
var credentials = new NetworkCredential(username, password);
// Create an Web transport for sending email.
var transportWeb = new Web(credentials);
// Send the email.
await transportWeb.DeliverAsync(myMessage);
As far as I can see I'm not getting any errors except when I debug and look at myMessage the Header has an error.
When I tried initializing a new empty header (var header = new Header();) I noticed there were still errors on that
To = 'header.To' threw an exception of type 'System.ArgumentException' Message = "Bad key path!"
Does anyone know what this means? Or if this could be causing the emails not to send?
The answer to your other question actually uses SendGrid:
Alerts for exceptions in an Azure worker role
There are three globalvariables:
public const string SmtpServerHost = "smtp.sendgrid.net";
public const string SmtpServerUserName = "[useridfromsendgrid#azure.com]";
public const string SmtpServerPassword = "[password from sendgrid]";
You actually do not need to use the SDK, just setup the account in Azure portal, and save your creds in your project.
You can send emails locally, but if you are on a work network, the firewall may block the emails from being sent. The code I posted I placed in an email service in my namespace.
It has be deployed to Azure to work. It won't work locally.
I am developing a MVC 5 internet application, and am wishing to send an email using the SendGrid service when my application is deployed to Azure.
I have found some resource links, yet each different code implementation that I use, sends the email very slowly. I have chosen to use the code from this link: http://www.codeproject.com/Articles/762427/ASP-NET-Identity-Setting-Up-Account-Validation-and
Here is my code:
public class EmailService : IIdentityMessageService
{
public Task SendAsync(IdentityMessage message)
{
// Credentials:
var sendGridUserName = "myusername";
var sentFrom = "test#email.com";
var sendGridPassword = "mypassword";
// Configure the client:
var client =
new System.Net.Mail.SmtpClient("smtp.sendgrid.net", Convert.ToInt32(587));
client.Port = 587;
client.DeliveryMethod = System.Net.Mail.SmtpDeliveryMethod.Network;
client.UseDefaultCredentials = false;
// Creatte the credentials:
System.Net.NetworkCredential credentials =
new System.Net.NetworkCredential(sendGridUserName, sendGridPassword);
client.EnableSsl = true;
client.Credentials = credentials;
// Create the message:
var mail =
new System.Net.Mail.MailMessage(sentFrom, message.Destination);
mail.Subject = message.Subject;
mail.Body = message.Body;
// Send:
return client.SendMailAsync(mail);
}
}
The email takes many minutes to send. Why is this? How fast should the email be sent on average, and do I need to optimize my code in any way? Also, rather than using SendGrid, is there a better resource to use that I should use?
Thanks in advance.
Somewhere on Sendgrid documentation (can't find it now unfortunately) I have seen recommendation that if you use their REST API endpoints instead of SMPT, the emails will arrive quicker. And Sendgrid provides C# library to use their API. Give it a go.
It's possible SendGrid is deferring or delaying your sends. Is there any defer or delay activity in your SendGrid dashboard?
You can also connect to the SendGrid Webhook Events to see exactly what's going on with your emails.