I am using a Function app to trigger a mail, using MS Graph API, the mail body text is getting triggered properly but facing issue in rendering the header and footer image shown in picture. How to solve this issue in the body level.
Below are the references of the above images in HTML/Blob file
<img src=cid:Header.jpg>
<img src=cid:footer.png>
<ContentIDs>Header.jpg, footer.png</ContentIDs>
Code used in rendering the body.
var mailContent = new Message
{
Subject = em.Subject,
Body = new ItemBody
{
ContentType = BodyType.Html,
Content = m.Body,
ODataType = null
},
ToRecipients = toEmails,
CcRecipients = ccEmails,
ODataType = null
};
EDIT:
Currently facing bad request in Function App after this changes. I am trying to resolve that. If you see any discrepancy in this below code feel free to comment.
var imagePath = #"<path\Header.jpg>";
var imageID = "Header.jpg";//file name
byte[] imageArray = System.IO.File.ReadAllBytes(imagePath);
var imagePath2 = #"<path\footer.png">;
var imageID2 = "footer.png";
byte[] imageArray2 =System.IO.File.ReadAllBytes(imagePath2);
var mContent = new Message
{
Subject = t.Subject,//parsing from the template
Body = new ItemBody
{
ContentType = BodyType.Html,
Content = m.Body,
ODataType = "#microsoft.graph.fileAttachment"
},
ToRecipients = toEmails,
CcRecipients = ccEmails,
ODataType = "#microsoft.graph.fileAttachment",
HasAttachments = true,
Attachments = new MessageAttachmentsCollectionPage()
{
new FileAttachment
{
ContentBytes= imageArray,
ContentType = "image/jpeg",
ContentId= imageID,
IsInline=true,
Name = "theHead",
},
new FileAttachment
{
ContentBytes= imageArray2,
ContentType = "image/png",
ContentId= imageID2,
IsInline=true,
Name = "thefoot",
}
}
};
I write a demo for you , try the simple console app below:
using Microsoft.Graph;
using Microsoft.Graph.Auth;
using Microsoft.Identity.Client;
using System;
using System.Collections.Generic;
namespace sendEmails
{
class Program
{
static void Main(string[] args)
{
var appID = "";
var appSec = "";
var tenantID = "";
IConfidentialClientApplication confidentialClientApplication = ConfidentialClientApplicationBuilder
.Create(appID)
.WithTenantId(tenantID)
.WithClientSecret(appSec)
.Build();
ClientCredentialProvider authenticationProvider = new ClientCredentialProvider(confidentialClientApplication);
GraphServiceClient graphServiceClient = new GraphServiceClient(authenticationProvider);
var imagePath = #"<your image path>";
var imageID = "image1";
byte[] imageArray = System.IO.File.ReadAllBytes(imagePath);
var body = "<h1>this is superman </br> <img src='cid:"+ imageID + "'/></h1>";
var attachments = new MessageAttachmentsCollectionPage()
{
new FileAttachment{
ContentType= "image/jpeg",
ContentBytes = imageArray,
ContentId = imageID,
Name= "test-image"
}
};
var message = new Message
{
Subject = "TEST SENDING IMAGE ",
Body = new ItemBody
{
ContentType = BodyType.Html,
Content = body,
ODataType = null
},
ToRecipients = new List<Recipient>()
{
new Recipient
{
EmailAddress = new EmailAddress
{
Address = "<receiver email>"
}
}
},
Attachments = attachments
};
graphServiceClient.Users["<user upn>"].SendMail(message, false).Request().PostAsync().GetAwaiter().GetResult();
Console.WriteLine("ok");
}
}
}
Result :
Related
I am developing an aplication that send and email with one or multiple attachments via Microsoft Graph, but when try to upload file send me an error: ": Invalid total bytes specified in the Content-Range header"
i asume that i must specifi Range Value in same where, but no idea.
This is my code:
private static async void SenMailUsingMicrosoftGraph(List<String>Destinations, List<String>Cc, string HidenCopy, string Body, string Title, List<FileInfo>Filess);
{
ClientSecretCredential credential = new ClientSecretCredential("MyTenantID", "MyClientId", "MyClientSecret");
List<Recipient> recipientsDestinatarios = new List<Recipient>();
List<Recipient> recipientsCopias = new List<Recipient>();
foreach (var c in Destinations)
{
recipientsDestinatarios.Add(
new Recipient
{
EmailAddress = new EmailAddress
{
Address = c
}
});
}
foreach (var mail in Cc)
{
recipientsCopias.Add(
new Recipient
{
EmailAddress = new EmailAddress
{
Address = mail
}
});
}
#endregion
var message = new Microsoft.Graph.Message
{
Subject = Title,
Body = new ItemBody
{
ContentType = BodyType.Html,
Content = Body
},
ToRecipients = recipientsDestinatarios
,
CcRecipients = recipientsCopias
,
BccRecipients = new List<Recipient>()
{
new Recipient
{
EmailAddress=new EmailAddress{Address=Hiden}
}
}
};
GraphServiceClient graphClient = new GraphServiceClient(credential);
#endregion
#region adjuntar ficheros
var msgResult = await graphClient.Users["myemail#mycompany.com"].MailFolders.Drafts.Messages
.Request()
.WithMaxRetry(9)
.AddAsync(message);
foreach (var Archivo in Filess)
{
var attachmentContentSize = Archivo.Length;
var attachmentItem = new AttachmentItem
{
AttachmentType = AttachmentType.File,
Name = Archivo.Name,
Size = attachmentContentSize,
};
//initiate the upload session for large files
var uploadSession = await graphClient.Users["myemail#mycompany.com"].Messages[msgResult.Id].Attachments
.CreateUploadSession(attachmentItem)
.Request()
.PostAsync();
var maxChunkSize = 1024 * 320;
var allBytes = System.IO.File.ReadAllBytes(Archivo.FullName);
using (var stream = new MemoryStream(allBytes))
{
stream.Position = 0;
LargeFileUploadTask<FileAttachment> largeFileUploadTask = new LargeFileUploadTask<FileAttachment>(uploadSession, stream, maxChunkSize);
await largeFileUploadTask.UploadAsync();
}
}
await graphClient.Users["myemail#mycompany.com"].Messages[msgResult.Id].Send().Request().PostAsync();
}
I try something like this:
var content = new System.Net.Http.Headers.ContentRangeHeaderValue(0,MyFile.Length-1,MyFile.Length);
but i dont now how to asign this content variable, i think that must go in the uploadSession but dont know how.
------------------------------------EDIT------------------------------
included a Picture where see that the size of the attachment is not zero
My one template is not replacing dynamics data in the email
My Code is given below
public static System.Net.HttpStatusCode SendEmailV2(DynamicsModel dynamicsmodel, string templateId, TraceWriter log)
{
log.Info("Executing SendEmailV2");
var SendGridApiCode = System.Environment.GetEnvironmentVariable("SendGridApiCode", EnvironmentVariableTarget.Process);
var fromEmail = System.Environment.GetEnvironmentVariable("FromEmail", EnvironmentVariableTarget.Process);
var fromName = System.Environment.GetEnvironmentVariable("FromName", EnvironmentVariableTarget.Process);
var dynamicTemplateData = new DynamicData
{
Name = dynamicsmodel.FullName
};
string output = JsonConvert.SerializeObject(dynamicTemplateData);
log.Info("json:" + output);
EmailAddress from = new EmailAddress(fromEmail, "test name");
EmailAddress to = new EmailAddress(dynamicsmodel.Email, dynamicsmodel.FullName);
var sendGridClient = new SendGridClient(SendGridApiCode);
var sendGridMessage = CreateSingleTemplateEmail(from, to, templateId, dynamicTemplateData);
var response = sendGridClient.SendEmailAsync(sendGridMessage).Result;
if (response.StatusCode == System.Net.HttpStatusCode.Accepted)
{
log.Info("Emails Sent from SendGrid");
}
else
{
log.Info("response.StatusCode:" + response.StatusCode.ToString());
}
return response.StatusCode;
}
My JSON which is being passed is given below
{"name":"Test User"}
This happens to one template only. Any help will be much appreciated
When calling GitHttpClient.CreateAnnotatedTagAsync, I keep getting "VS30063: You are not authorized to access https://dev.azure.com" even though my credentials are valid.
This is my code:
var vssConnection = new VssConnection(new Uri("ORG_URI"), new VssBasicCredential(string.Empty, "PAT"));
var gitClient = vssConnection.GetClient<GitHttpClient>();
var tag = new GitAnnotatedTag
{
Name = "tagname",
Message = "A new tag",
TaggedBy = new GitUserDate
{
Name = "Name",
Email = "Email",
Date = DateTime.Now,
ImageUrl = null
},
ObjectId = "SHA",
TaggedObject = new GitObject
{
ObjectId = "SHA",
ObjectType = GitObjectType.Commit
},
Url = string.Empty
};
var sourceRepo = await gitClient.GetRepositoryAsync("PROJECT", repoName);
// This call works
var tags = await gitClient.GetTagRefsAsync(sourceRepo.Id);
// The tag is printed to the console
Console.WriteLine(tags.First().Name);
// This throws "VS30063: You are not authorized to access https://dev.azure.com"
await gitClient.CreateAnnotatedTagAsync(tag, "PROJECT", sourceRepo.Id);
There is an issue with your PAT token. I just created a tag using your code and PAT with FULL Access:
Can you create a new token and try again?
After reading the migration infos from Google on the Gdrive.v3 SDK here: https://developers.google.com/drive/v3/web/migration, I#m still not really sure how I can set the ParentReference (to the root folder) for a file correctly. Currently in v2 this is done via:
private string UploadToGDrive( Google.Apis.Drive.v3.DriveService service, string uploadFile, string parent)
{
var body = new Google.Apis.Drive.v3.Data.File
{
Name = Path.GetFileName(uploadFile),
Description = uploadFile,
MimeType = GetMimeType(uploadFile),
Parents = new List<ParentReference> {new ParentReference {Id = parent}}
};
}
private string GetMimeType(string fileName)
{
var mimeType = "application/unknown";
var extension = Path.GetExtension(fileName);
if (extension == null) return mimeType;
var ext = extension.ToLower();
var regKey = Registry.ClassesRoot.OpenSubKey(ext);
if (regKey?.GetValue("Content Type") != null) return mimeType;
if (regKey != null) mimeType = regKey.GetValue("Content Type").ToString();
return mimeType;
}
As stated in the document - Inserting a file in a folder:
To insert a file in a particular folder, specify the correct ID in the parents property of the file, as shown:
var folderId = "0BwwA4oUTeiV1TGRPeTVjaWRDY1E";
var fileMetadata = new File()
{
Name = "photo.jpg",
Parents = new List<string>
{
folderId
}
};
FilesResource.CreateMediaUpload request;
using (var stream = new System.IO.FileStream("files/photo.jpg",
System.IO.FileMode.Open))
{
request = driveService.Files.Create(
fileMetadata, stream, "image/jpeg");
request.Fields = "id";
request.Upload();
}
var file = request.ResponseBody;
Console.WriteLine("File ID: " + file.Id);
Hope this helps.
I must have overseen this... It simply means in my case to replace
var body = new Google.Apis.Drive.v3.Data.File
{
Name = Path.GetFileName(uploadFile),
Description = uploadFile,
MimeType = GetMimeType(uploadFile),
Parents = new List<ParentReference> {new ParentReference {Id = parent}}
};
with
var body = new Google.Apis.Drive.v3.Data.File
{
Name = Path.GetFileName(uploadFile),
Description = uploadFile,
MimeType = GetMimeType(uploadFile),
Parents = new List<string> {parent}
};
(I've added this as an answer as it is to long for a comment).
Am using DocuSign Api's for signing documents. Now I have created template in DocuSign and Uploaded the PDF's there.
Now when user click's on submit, we need to auto populate docusign pdf's and I don't have custom fields added at docusign and it should be dynamic. Below is the code which is not working.
public string SignDocument()
{
var accountId = Login();
var url = GetRecipientDocumentUrl(accountId);
return url;
}
private string Login()
{
string authHeader = "{\"Username\":\"" + Username + "\", \"Password\":\"" + Password + "\", \"IntegratorKey\":\"" + IntegratorKey + "\"}";
DocuSign.eSign.Client.Configuration.Default.AddDefaultHeader("X-DocuSign-Authentication", authHeader);
// we will retrieve this from the login() results
string accountId = null;
// the authentication api uses the apiClient (and X-DocuSign-Authentication header) that are set in Configuration object
var authApi = new AuthenticationApi();
LoginInformation loginInfo = authApi.Login();
// find the default account for this user
foreach (LoginAccount loginAcct in loginInfo.LoginAccounts)
{
if (loginAcct.IsDefault == "true")
{
accountId = loginAcct.AccountId;
break;
}
}
if (accountId == null)
{ // if no default found set to first account
accountId = loginInfo.LoginAccounts[0].AccountId;
}
return accountId;
}
private string GetRecipientDocumentUrl(string accountId)
{
//var envelope = BuildEnvelopeDefinition(documents);
var envelope = BuildEnvelopeDefinition();
// |EnvelopesApi| contains methods related to creating and sending Envelopes (aka signature requests)
var envelopesApi = new EnvelopesApi();
//TemplateCustomFields
var summary = envelopesApi.CreateEnvelope(accountId, envelope);
//===========================================================
// Step 3: Create Embedded Signing View (URL)
//===========================================================
var viewOptions = BuildRecipientViewRequest(envelope);
var recipientView = envelopesApi.CreateRecipientView(accountId, summary.EnvelopeId, viewOptions);
return recipientView.Url;
}
private EnvelopeDefinition BuildEnvelopeDefinition()
{
TemplateRole templateRole = new TemplateRole();
templateRole.Email = "kpothireddy#firstam.com";
templateRole.Name = "Sample";
templateRole.RoleName = "1";
templateRole.Tabs = new Tabs();
templateRole.Tabs.TextTabs = new List<Text>();
Text textTab = new Text();
textTab.TabLabel = "Approved by";
textTab.Value = "Kranthi";
//textTab.XPosition = "100";
//textTab.YPosition = "100";
templateRole.Tabs.TextTabs.Add(textTab);
templateRole.ClientUserId = Guid.NewGuid().ToString();
List<TemplateRole> rolesList = new List<TemplateRole>();
rolesList.Add(templateRole);
//rolesList.Add(templateRole1);
var envelope = new EnvelopeDefinition
{
TemplateRoles = rolesList,
//TemplateId = "3b07a774-5ec5-4bbd-928a-a4b0bace2fc5",
TemplateId = "44d25c06-4fc3-4cbe-a9d0-7e0e1e3013bc", //Prefill
Status = "sent"
};
//Envelope e = new Envelope();
return envelope;
}
private RecipientViewRequest BuildRecipientViewRequest(EnvelopeDefinition envelope)
{
RecipientViewRequest viewOptions = new RecipientViewRequest()
{
ReturnUrl = ReturnUrl,
ClientUserId = envelope.TemplateRoles.First().ClientUserId, // must match clientUserId set in step #2!
AuthenticationMethod = "email",
UserName = envelope.TemplateRoles.First().Name,
Email = envelope.TemplateRoles.First().Email
//UserName = envelope.Recipients.Signers.First().Name,
//Email = envelope.Recipients.Signers.First().Email
};
return viewOptions;
}
Could you please help me out.