Reputation: 65
I'm building a recruitment bot for a company. The main mission of this bot is to get info from candidat, including his resume and to get all that sent by email.
I'm using FormFlow (basic) instead of dialogs, and here is the code where i get the file
[AttachmentContentTypeValidator(ContentType = "pdf")]
[Prompt("please, provide us your resume")]
public AwaitableAttachment file_CV;
[Prompt("Your email ?")]
public string email;
public static IForm<ProfileForm> BuildForm()
{
return new FormBuilder<ProfileForm>()
.Message("thank you")
.Build();
}
If I'm not wrong, the attachment file is converted to a blob in a local storage, but in production, how should i retrieve this file to get it sent by email to the email job company? Using azure storage maybe?
Thank you.
Upvotes: 1
Views: 324
Reputation: 581
I've created an example bot here for this, as it is relatively involved. The important code is within ImagesForm.cs. The form itself stays the same, however when you create your form you will want to make sure to include onCompletion:
return new FormBuilder<ImagesForm>()
.Message("Welcome, please submit all required documents")
.OnCompletion(onFormCompleted)
.Build();
This will allow you to work with the responses submitted by the user.
To forward the information to an email, you have to create a proactive email message from the bot to another account (this also means you have to make sure you've got an email channel set
var botAccount = new ChannelAccount(name: $"{ConfigurationManager.AppSettings["BotId"]}", id: $"{ConfigurationManager.AppSettings["BotEmail"]}".ToLower()); //botemail is cast to lower so that it can be recognized as valid
var userAccount = new ChannelAccount(name: "Name", id: $"{ConfigurationManager.AppSettings["UserEmail"]}");//all of these are additional fields within application settings
MicrosoftAppCredentials.TrustServiceUrl(@"https://email.botframework.com/", DateTime.MaxValue); //a call to TrustServiceUrl is required to send a proactive message to a channel different from the one the user is actively using.
var connector = new ConnectorClient(new Uri("https://email.botframework.com/" ));
var conversationId = await connector.Conversations.CreateDirectConversationAsync(botAccount, userAccount);
IMessageActivity message = Activity.CreateMessageActivity();
message.From = botAccount;
message.Recipient = userAccount;
message.Conversation = new ConversationAccount(id: conversationId.Id);
message.Text = $"Resume recieved from {state.email.ToString()}"; //the actual body of the email
message.Locale = "en-Us";
message.Attachments = new List<Attachment>();
message.Attachments.Add(state.file_CV.Attachment);
After this, you just have to send the email to the email channel
try
{
await connector.Conversations.SendToConversationAsync((Activity)message);
}
catch (ErrorResponseException e)
{
Console.WriteLine("Error: ", e.StackTrace);
}
NOTE This will NOT work on localhost, as the attachment includes a ContentUrl that points to an http localhost endpoint while the email channel requires an https endpoint. Make sure you deploy on azure to actually test this functionality.
Upvotes: 0
Reputation: 27825
As you mentioned in comment, it seems that the attached pdf file that user provided is stored as attachment in channel's blob storage.
If you’d like to store the pdf file that user provided in custom store, such as Azure Blob Storage, you can access attachment based on ContentUrl
and upload it to Azure Blob Storage within validation function.
Code snippet:
.Field(nameof(file_CV),
validate: async (state, value) =>
{
var val = (AwaitableAttachment)value;
var url = val.Attachment.ContentUrl;
var aname = val.Attachment.Name;
HttpClient httpClient = new HttpClient();
Stream filestrem = await httpClient.GetStreamAsync(url);
httpClient.Dispose();
var storageAccount = CloudStorageAccount.Parse("{storage_connect_string}");
var blobClient = storageAccount.CreateCloudBlobClient();
var cloudBlobContainer = blobClient.GetContainerReference("useruploads");
await cloudBlobContainer.CreateIfNotExistsAsync();
CloudBlockBlob blockBlob = cloudBlobContainer.GetBlockBlobReference(aname);
blockBlob.UploadFromStream(filestrem);
((AwaitableAttachment)value).Attachment.ContentUrl = blockBlob.Uri.ToString();
var result = new ValidateResult { IsValid = true, Value = value };
return result;
})
Test result:
Upvotes: 1