I want to trigger mail when the bot says that it has no answer - email

I want to trigger mail when the bot says that it has no answer.
I'm using MS bot framework SDk4, and using LUIS and QnA maker also, when the bot reached the to a point where it says that it has no answer , we want a mail to be triggered or add a new item in the sharepoint

If you want to add a no answer to a SharePoint List, I managed to get it working using the csom-node package and Bot Framework v4 / NodeJS. Granted, it's not the most elegant solution, but it works.
Bot.JS
const csomapi = require('../node_modules/csom-node');
settings = require('../settings').settings;
// Set CSOM settings
csomapi.setLoaderOptions({url: settings.siteurl});
Bit further down the page...
// If no answers were returned from QnA Maker, reply with help.
} else {
await context.sendActivity("Er sorry, I don't seem to have an answer.");
console.log(context.activity.text);
var response = context.activity.text;
var authCtx = new AuthenticationContext(settings.siteurl);
authCtx.acquireTokenForApp(settings.clientId, settings.clientSecret, function (err, data) {
var ctx = new SP.ClientContext("/sites/yoursite"); //set root web
authCtx.setAuthenticationCookie(ctx); //authenticate
var web = ctx.get_web();
var list = web.get_lists().getByTitle('YourList');
var creationInfo = new SP.ListItemCreationInformation();
var listItem = list.addItem(creationInfo);
listItem.set_item('Title', response);
listItem.update();
ctx.load(listItem);
ctx.executeQueryAsync();
});
}

Proactive Messaging doesn't really work for email (to prevent spam), so you're better off not using the Bot Framework SDK for the email portion. #Baruch's link, How to send email in ASP.NET C# is good if you're using the C# SDK. Here's one for sending emails in Node.
All you have to do is send the email when QnA Maker doesn't return any results. In this sample, you would do so here:
if (response != null && response.Length > 0)
{
await turnContext.SendActivityAsync(MessageFactory.Text(response[0].Answer), cancellationToken);
}
else
{
await turnContext.SendActivityAsync(MessageFactory.Text("No QnA Maker answers were found."), cancellationToken);
// Add code that sends Notification Email
}
That being said, if you'd like to try a semi-proactive route, you can enable the Email Channel in your bot, then use this:
if (response != null && response.Length > 0)
{
await turnContext.SendActivityAsync(MessageFactory.Text(response[0].Answer), cancellationToken);
}
else
{
await turnContext.SendActivityAsync(MessageFactory.Text("No QnA Maker answers were found."), cancellationToken);
MicrosoftAppCredentials.TrustServiceUrl(#"https://email.botframework.com/", DateTime.MaxValue);
var user = new ChannelAccount(name: "MyUser", id: "<notified Email Address>");
var parameters = new ConversationParameters()
{
Members = new ChannelAccount[] { user },
Bot = turnContext.Activity.Recipient
};
var connector = new ConnectorClient(new Uri("https://email.botframework.com"), "<appId>", "<appPassword>");
var conversation = await connector.Conversations.CreateConversationAsync(parameters);
var activity = MessageFactory.Text("This is a notification email");
activity.From = parameters.Bot;
activity.Recipient = user;
await connector.Conversations.SendToConversationAsync(conversation.Id, activity);
}
The catch is that <notified Email Address> has to send a message to the bot before any notifications will work. If it doesn't, it will return a 401: Unauthorized error. Again, I don't recommend this route.
Note: If you're using the Dispatch sample, you'd place the code here:
private async Task ProcessSampleQnAAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
_logger.LogInformation("ProcessSampleQnAAsync");
var results = await _botServices.SampleQnA.GetAnswersAsync(turnContext);
if (results.Any())
{
await turnContext.SendActivityAsync(MessageFactory.Text(results.First().Answer), cancellationToken);
}
else
{
// PLACE IT HERE
await turnContext.SendActivityAsync(MessageFactory.Text("Sorry, could not find an answer in the Q and A system."), cancellationToken);
}
}

Related

How to implement Microsoft Graph deferred sending

I am trying to implement a deferred sending function to my site which currently sends email via Microsoft Graph. I have found some articles about SingleValueLegacyExtendedProperty being used to defer sending, but so far has been unsuccessful with it.
My current code just ignores the deferred sending time and sends the email immediately.
var message = new Message
{
Subject = Subject,
Body = new ItemBody
{
ContentType = BodyType.Html,
Content = bodyText
},
ToRecipients = new List<Recipient>()
{
new Recipient
{
EmailAddress = new EmailAddress
{
Address = recipient
}
}
},
};
message.SingleValueExtendedProperties = new MessageSingleValueExtendedPropertiesCollectionPage
{
new SingleValueLegacyExtendedProperty()
{
Id = "SystemTime 0x3FEF",
Value = DateTimeToSend.ToString("o")
}
};
var saveToSentItems = true;
await graphServiceClient.Me
.SendMail(message, saveToSentItems)
.Request()
.PostAsync();
In this article they suggest that the ID should be String {8ECCC264-6880-4EBE-992F-8888D2EEAA1D} Name pidTagDeferredSendTime when passing as JSON but it looks like that was not successful for other. I checked and can confirm that it did not work for me either.
Its important that the DateTime that you want the message to be sent is in UTC eg
"value": "2022-08-01T23:39:00Z"
Using local time won't work as Exchange does everything in UTC

Power BI REST API ExportToFileInGroup Not Working

I am able to programmatically log in to the PowerBI Client, gather my Workspaces as well as get a specific Report from a specific Workspace. I need to programmatically render that report to a .pdf or .xlsx file. Allegedly this is possible with the ExportToFileInGroup/ExportToFileInGroupAsync methods. I even created a very simple report without any parameters. I can embed this using the sample app from here. So that at least tells me that I have what I need setup in the backend. But it fails when I try to run the ExportToFileInGroupAsync method (errors below code.)
My Code is:
var accessToken = await tokenAcquisition.GetAccessTokenForUserAsync(new string[] {
PowerBiScopes.ReadReport,
PowerBiScopes.ReadDataset,
});
var userInfo = await graphServiceClient.Me.Request().GetAsync();
var userName = userInfo.Mail;
AuthDetails authDetails = new AuthDetails {
UserName = userName,
AccessToken = accessToken,
};
var credentials = new TokenCredentials($"{accessToken}", "Bearer");
PowerBIClient powerBIClient = new PowerBIClient(credentials);
var groups = await powerBIClient.Groups.GetGroupsAsync();
var theGroup = groups.Value
.Where(x => x.Name == "SWIFT Application Development")
.FirstOrDefault();
var groupReports = await powerBIClient.Reports.GetReportsAsync(theGroup.Id);
var theReport = groupReports.Value
.Where(x => x.Name == "No Param Test")
.FirstOrDefault();
var exportRequest = new ExportReportRequest {
Format = FileFormat.PDF,
};
string result = "";
try {
var response = await powerBIClient.Reports.ExportToFileInGroupAsync(theGroup.Id, theReport.Id, exportRequest);
result = response.ReportId.ToString();
} catch (Exception e) {
result = e.Message;
}
return result;
It gets to the line in the try block and then throws the following errors:
An error occurred while sending the request.
Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host..
UPDATE
Relating to #AndreyNikolov question, here is our Embedded capacity:
After this was implemented, no change. Same exact error.
Turns out the issue was on our side, more specifically, security/firewall settings. Here is the exact quote from our networking guru.
"After some more investigation we determined that our firewall was causing this issue when it was terminating the SSL connection. We were able to add a bypass for the URL and it is now working as expected."

xamarin forms: Calling phone and sending email (IOS, Android and UWP)

Currently using following code for calling and email features, but it is only working in Android and not working in IOS. Also, I need these features in UWP.
For call:
string phoneno = "1234567890";
Device.OpenUri(new Uri("tel:" + phoneno));
For mail:
string email = "sreejithsree139#gmail.com";
Device.OpenUri(new Uri("mailto:" + email ));
Any package available for this?
Xamarin.Essentials (Nuget) is available as a preview package and contains functionality to both open the default mail app and attach information such as the recipients, subject and the body as well as open the phone dialer with a certain number.
There is also a blog post about Xamarin.Essentials available on blog.xamarin.com.
Edit:
As for your mail issue, Xamarin.Essentials expects an array of strings as recipients so you are able to send mail to multiple people at once. Just pass a string array with one single value.
var recipients = new string[1] {"me#watercod.es"};
If you're using the overload that expects an EmailMessage instance, you are supposed to pass a List of string objects.
In that case, the following should work:
var recipients = new List<string> {"me#watercod.es"};
Updating the complete code for calling and mailing features using Xamarin.Essentials, this might help others.
For call:
try
{
PhoneDialer.Open(number);
}
catch (ArgumentNullException anEx)
{
// Number was null or white space
}
catch (FeatureNotSupportedException ex)
{
// Phone Dialer is not supported on this device.
}
catch (Exception ex)
{
// Other error has occurred.
}
For Mail:
List<string> recipients = new List<string>();
string useremail = email.Text;
recipients.Add(useremail);
try
{
var message = new EmailMessage
{
//Subject = subject,
//Body = body,
To = recipients
//Cc = ccRecipients,
//Bcc = bccRecipients
};
await Email.ComposeAsync(message);
}
catch (Exception ex)
{
Debug.WriteLine("Exception:>>"+ex);
}
Hello to make a call in UWP:
if (Windows.Foundation.Metadata.ApiInformation.IsTypePresent("Windows.ApplicationModel.Calls.PhoneCallManager"))
{
Windows.ApplicationModel.Calls.PhoneCallManager.ShowPhoneCallUI("123", "name to call");
}
To send a Text:
private async void ComposeSms(Windows.ApplicationModel.Contacts.Contact recipient,
string messageBody,
StorageFile attachmentFile,
string mimeType)
{
var chatMessage = new Windows.ApplicationModel.Chat.ChatMessage();
chatMessage.Body = messageBody;
if (attachmentFile != null)
{
var stream = Windows.Storage.Streams.RandomAccessStreamReference.CreateFromFile(attachmentFile);
var attachment = new Windows.ApplicationModel.Chat.ChatMessageAttachment(
mimeType,
stream);
chatMessage.Attachments.Add(attachment);
}
var phone = recipient.Phones.FirstOrDefault<Windows.ApplicationModel.Contacts.ContactPhone>();
if (phone != null)
{
chatMessage.Recipients.Add(phone.Number);
}
await Windows.ApplicationModel.Chat.ChatMessageManager.ShowComposeSmsMessageAsync(chatMessage);
}
as found in Microsoft documentation here: Compose SMS documentation
==> So you can make (If not already done) a shared service interface in your Xamarin app, then the implementation with these codes in your UWP app...
To send an email:
To send an email in UWP, you can refer to the Microsoft documentation too:
Send Email documentation (UWP)
Using a plugin
Else you can use a Xamarin plugin:
documentation: Xamarin cross messaging plugin
Nuget: Nuget plugin package
In our app, we are doing the phone calling with a DependencyService.
Therefore in our PCL, we have
public interface IPhoneCall
{
void Call(string number);
}
On the iOS side, the following method does the calling:
public void Call(string number)
{
if (string.IsNullOrEmpty(number))
return;
var url = new NSUrl("tel:" + number);
if (!UIApplication.SharedApplication.OpenUrl(url))
{
var av = new UIAlertView("Error",
"Your device does not support calls",
null,
Keys.Messages.BUTTON_OK,
null);
av.Show();
}
}
If don't want to wait for the Xamarin essentials that is still in pre-release as of today, you can use this open source plugin. It works on iOS, Android and UWP. There is a sample from the github documentation :
// Make Phone Call
var phoneDialer = CrossMessaging.Current.PhoneDialer;
if (phoneDialer.CanMakePhoneCall)
phoneDialer.MakePhoneCall("+27219333000");
// Send Sms
var smsMessenger = CrossMessaging.Current.SmsMessenger;
if (smsMessenger.CanSendSms)
smsMessenger.SendSms("+27213894839493", "Well hello there from Xam.Messaging.Plugin");
var emailMessenger = CrossMessaging.Current.EmailMessenger;
if (emailMessenger.CanSendEmail)
{
// Send simple e-mail to single receiver without attachments, bcc, cc etc.
emailMessenger.SendEmail("to.plugins#xamarin.com", "Xamarin Messaging Plugin", "Well hello there from Xam.Messaging.Plugin");
// Alternatively use EmailBuilder fluent interface to construct more complex e-mail with multiple recipients, bcc, attachments etc.
var email = new EmailMessageBuilder()
.To("to.plugins#xamarin.com")
.Cc("cc.plugins#xamarin.com")
.Bcc(new[] { "bcc1.plugins#xamarin.com", "bcc2.plugins#xamarin.com" })
.Subject("Xamarin Messaging Plugin")
.Body("Well hello there from Xam.Messaging.Plugin")
.Build();
emailMessenger.SendEmail(email);
}

Microsoft Bot Framework channel integration: more endpoints?

I'm using Microsoft Bot Framework using the channel registration product and the REST API. I have setup the "messaging endpoint" and everything works fine for sending and receiving messages.
But I don't just want to send/receive messages. Something as simple as setting up a welcome message seems impossible because my endpoint receives nothing other than messaging events (when the bot is in the channel / conversation.)
Is there something I have missed?
I would like to setup several endpoints, or use the same, whatever, to listen to other types of events.
You need to implement in the MessageController something like these:
Pay attention in the else if. The funcition in the controller is HandleSystemMessage.
else if (message.Type == ActivityTypes.ConversationUpdate)
{
// Handle conversation state changes, like members being added and removed
// Use Activity.MembersAdded and Activity.MembersRemoved and Activity.Action for info
// Not available in all channels
IConversationUpdateActivity update = message;
var cliente = new ConnectorClient(new System.Uri(message.ServiceUrl), new MicrosoftAppCredentials());
if (update.MembersAdded != null && update.MembersAdded.Count > 0)
{
foreach(var member in update.MembersAdded)
{
if(member.Id != message.Recipient.Id)
{
//var username = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
var username = message.From.Name;
var reply = message.CreateReply();
//string dir = System.AppDomain.CurrentDomain.BaseDirectory + "Images" + Path.DirectorySeparatorChar + "cajamar.png";
string dir = HttpRuntime.AppDomainAppPath + "Images" + Path.DirectorySeparatorChar + "cajamar.png";
reply.Attachments.Add(new Attachment(
contentUrl: dir,
contentType: "image/png",
name: "cajamar.png"
));
reply.Text = $"Bienvenido {username} al ChatBot de convenios:";
cliente.Conversations.ReplyToActivity(reply);
//var reply = message.CreateReply();
//reply.Text = $"El directorio base es: {HttpRuntime.AppDomainAppPath}";
//cliente.Conversations.ReplyToActivityAsync(reply);
}
}
}
}

DotNetOpenAuth Get Facebook Email Address

I have the following code where its grabbing First/Last name. I realize that email is an extended permission, but what would I need to modify to request extended permissions?
How do I get the email of an authenticated Facebook user through the DotNetOpenAuth?
fbClient = new FacebookClient
{
ClientIdentifier = ConfigurationManager.AppSettings["facebookAppID"],
ClientSecret = ConfigurationManager.AppSettings["facebookAppSecret"],
};
IAuthorizationState authorization = fbClient.ProcessUserAuthorization();
if (authorization == null)
{
// Kick off authorization request
fbClient.RequestUserAuthorization();
}
else
{
var request = WebRequest.Create("https://graph.facebook.com/me?access_token=" + Uri.EscapeDataString(authorization.AccessToken));
using (var response = request.GetResponse())
{
using (var responseStream = response.GetResponseStream())
{
var graph = FacebookGraph.Deserialize(responseStream);
// unique id for facebook based on their ID
FormsAuthentication.SetAuthCookie("fb-" + graph.Id, true);
return RedirectToAction("Index", "Admin");
}
}
}
return View("LogOn");
Add the following bits:
var scope = new List<string>();
scope.Add("email");
fbClient.RequestUserAuthorization(scope);
If you are using VS2012 built in oauth providers you just need to update your oauth package. See the last post on the following link: http://forums.asp.net/t/1847724.aspx/1. The only email I can't retrieve is MS Live. Currently I use facebook, google, and yahoo.