Microsoft Bot Framework: broadcast messages to users from database - c#

Situation: When a user registers for a bot (by entering a message to the bot, I store the information of that user in a database:
- UserId
- UserName,
- ServiceURL
At some point in time I want to have my bot broadcast a message to all the users in that table.
foreach (var bUsers in users)
{
MicrosoftAppCredentials.TrustServiceUrl(bUsers.ServiceUrl);
MicrosoftAppCredentials creds = new MicrosoftAppCredentials("<<appid>>", "<<secret>>");
var connector = new ConnectorClient(new Uri(bUsers.ServiceUrl), creds);
var conversationId = await connector.Conversations.CreateDirectConversationAsync(new ChannelAccount(), new ChannelAccount(bUsers.UserId, bUsers.UserName));
message = Activity.CreateMessageActivity();
message.From = botAccount;
message.Recipient = userAccount;
message.Conversation = new ConversationAccount(id: conversationId.Id);
message.Text = "Hello from " + context.Activity.From.Name;
message.Locale = "en-Us";
var reply = await connector.Conversations.SendToConversationAsync((Activity) message);
}
With this code, I get a message saying:
Invalid conversation ID in teamsChannelId
I don't understand this message, and is it even possible to do what I want?

I was doing almost the same thing as you do but it stopped working suddenly. I could see the same error message.
But in my case it was just wrong and maybe it's strange it worked in the first place. Because I used client.UserId which was set to activity.Conversation.Id. If I changed the code to use it as conversationId it works.
Here is my code which is working right now and old pieces are commented out:
public static async Task SendMessageToClient(ServerClient client, string messageText)
{
var connector = new ConnectorClient(new Uri(client.BotServiceUrl), new MicrosoftAppCredentials());
var userAccount = new ChannelAccount(name: client.UserName, id: client.UserId);
var botAccount = new ChannelAccount(name: client.BotName, id: client.BotId);
// this worked before but not anymore
//var conversationId = await connector.Conversations
// .CreateDirectConversationAsync(botAccount, userAccount).Id;
// because client.UserId was set in a MessageController to activity.Conversation.Id we can use this
var conversationId = client.UserId;
var message = Activity.CreateMessageActivity();
message.From = botAccount;
message.Recipient = userAccount;
message.Conversation = new ConversationAccount(false, conversationId);
message.Locale = "en-Us";
if (client.ReplaceFrom != null && client.ReplaceTo != null)
{
messageText = messageText.Replace(client.ReplaceFrom, client.ReplaceTo);
}
message.Text = messageText;
await connector.Conversations.SendToConversationAsync((Activity) message);
}

Related

How to withdraw a scheduled email sent with microsoft graph api?

I use the below code. Now I would like to withdraw the email. How?
I tried to set the Id and then delete it. But it says "malformated Id". Also, I´m not sure if this would stop the mail.
var message = new Message
{
Subject = "Meet for lunch later withID?",
InternetMessageId = "88dc8516-103a-7df2-2685-1ce9045941b5",
Body = new ItemBody
{
ContentType = BodyType.Text,
Content = "The new cafeteria is open."
},
ToRecipients = new List<Recipient>()
{
new Recipient
{
EmailAddress = new EmailAddress
{
Address = "doe#gmail.com"
}
}
}
,
SingleValueExtendedProperties =
new MessageSingleValueExtendedPropertiesCollectionPage()
{
new SingleValueLegacyExtendedProperty
{
Id = "SystemTime 0x3FEF",
Value = DateTime.UtcNow.AddMinutes(5).ToString("o")
}
}
};
var saveToSentItems = false;
await graphClient.Me
.SendMail(message, saveToSentItems)
.Request()
.PostAsync();
Instead of sending the email with a schedule you need to create a draft with a schedule.
var email = await graphClient.Me.Messages
.Request()
.AddAsync(message);
await graphClient.Me.Messages[email.Id]
.Send()
.Request()
.PostAsync();
Now this returns the message object with the id. This id can now be used to delete the scheduled email.
await graphClient.Me.Messages[email.Id]
.Request()
.DeleteAsync();

Sending email to multiple recipients fails

I am trying to send the same automatic email to multiple email addresses but I can't get it to work.
[HttpGet("largeorderemail")]
public IActionResult LargeOrderEmail()
{
try
{
//var bodyString = $"<h3>{msg}</h3><br/><p> Visit the site <a href='{Startup.appSettings.AllowOrigin}/lidarweb'> LiDAR GIS portal.</a></p>";
var bodyString = $"<h3>email body</h3>" +
<br/>" +
var emailService = new Email { To = "info#tel.net" };
var response = emailService.ExecuteLargeOrder(bodyString);
return Ok();
}
catch (Exception e)
{
Log.Error(e);
return NotFound();
}
}
public async Task<Response> ExecuteLargeOrder(string bodyString)
{
var fromAddr = new EmailAddress(from, "Info");
subject = "large order";
var toAddr = new EmailAddress(to, "User");
plainTextContent = "";
htmlContent = bodyString;
var msg = MailHelper.CreateSingleEmail(fromAddr, toAddr, subject, plainTextContent, htmlContent);
var response = await client.SendEmailAsync(msg);
return response;
}
When I send an email to a single address, it works. Like so: var emailService = new Email { To = "info#tel.net" };
but when I try something like this, it doesn't send the email var emailService = new Email { To = "info#tel.net, info#gmail.com" };
I also tried separating the address like so var emailService = new Email { To = "info#tel.net; info#gmail.com" }; but this also doesn't work.
Any suggestions?
Instead of putting Email addresses, try doing this way. Keep all your Email address in Array and try looping through the Array so that you can achieve your goal.

How to Set [Activity.From.Id] , [member.Id] or [activity.Recipient.Id] using DirectLine?

I'm using MS directline to integrate custom channel with a chatbot based on botframework.
I'm using below functions to generate token & start conversation, but none of them allows to set Context.Activity.From.Id, MembersAdded.FirstOrDefault().Id , nor Activity.Recipient.Id
GenerateTokenForNewConversationAsync()
StartConversationAsync()
I Know we can control the ID when we send the first user message through directline , but I want to control any of the above IDs before even sending a message from the user. I want to set a specific ID and be able to capture it on the BOT event OnTurnAsync and Activity of type ActivityTypes.ConversationUpdate .. what should I do ?
Regarding my comment, I decided I'd just provide how to do what you want with both packages. Again, if it isn't too much trouble to switch, I highly, highly recommend using Microsoft.Bot.Connector (newer and more frequently updated) over Microsoft.Bot.Connector.DirectLine (older, not updated in 2.5 years, and deprecated until/unless we open-source it Update: This isn't actually deprecated, yet. We're currently working on open-sourcing this, but it's a low-priority task).
Recommended: Microsoft.Bot.Connector
Create the conversation with To and From, all-in-one.
var userAccount = new ChannelAccount(toId,toName);
var botAccount = new ChannelAccount(fromId, fromName);
var connector = new ConnectorClient(new Uri(serviceUrl));
IMessageActivity message = Activity.CreateMessageActivity();
if (!string.IsNullOrEmpty(conversationId) && !string.IsNullOrEmpty(channelId))
{
message.ChannelId = channelId;
}
else
{
conversationId = (await connector.Conversations.CreateDirectConversationAsync( botAccount, userAccount)).Id;
}
message.From = botAccount;
message.Recipient = userAccount;
message.Conversation = new ConversationAccount(id: conversationId);
message.Text = "Hello, this is a notification";
message.Locale = "en-Us";
await connector.Conversations.SendToConversationAsync((Activity)message);
Credit
Not Recommended: Microsoft.Bot.Connector.DirectLine
This is kind of a hacky workaround, but basically, you create the conversation and then send a ConversationUpdate activity.
//server side, retrieve token from secret
string directLineSecret = ConfigurationManager.AppSettings["DirectLineSecret"];
HttpClient httpClient = new HttpClient();
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post,$"https://directline.botframework.com/v3/directline/tokens/generate");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", directLineSecret);
var fromUser = $"dl_{Guid.NewGuid()}";
request.Content = new StringContent(
JsonConvert.SerializeObject(
new { User = new { Id = fromUser } }),
Encoding.UTF8,
"application/json");
var response = await httpClient.SendAsync(request);
DirectLineToken dlToken = null;
if (response.IsSuccessStatusCode)
{
var body = await response.Content.ReadAsStringAsync();
dlToken = JsonConvert.DeserializeObject<DirectLineToken>(body);
}
string token = dlToken.token;
//create DirectLineClient from token, client side
DirectLineClient client = new DirectLineClient(token);
var conversation = await client.Conversations.StartConversationAsync();
new System.Threading.Thread(async () => await ReadBotMessagesAsync(client, conversation.ConversationId)).Start();
//send conversationUpdate
var user = new ChannelAccount(fromUser);
await client.Conversations.PostActivityAsync(conversation.ConversationId,
new Activity
{
From = user,
Text = string.Empty,
Type = ActivityTypes.ConversationUpdate,
MembersAdded = new[] { user }
}
);
TimeSpan delayTime = TimeSpan.FromSeconds(dlToken.expires_in) - TimeSpan.FromMinutes(5);
Task.Factory.StartNew(async () =>
{
while (!_getTokenAsyncCancellation.IsCancellationRequested)
{
var t = await client.Tokens.RefreshTokenAsync().ConfigureAwait(false);
await Task.Delay(delayTime, _getTokenAsyncCancellation.Token).ConfigureAwait(false);
}
}).ConfigureAwait(false);
Credit

SendGrid Add Category to mail

I am using SendGrid, and I want to add one or more category to the email, but the added category hadn't been sent!
This is the code:
internal class Example
{
private static void Main()
{
Execute().Wait();
}
static async Task Execute()
{
//FYI, the following three variables are not real
var apiKey = "SG.XXX";
var fromEmail = "";
var toEmail = "";
var client = new SendGridClient(apiKey);
var from = new EmailAddress(fromEmail);
var subject = "Sending with SendGrid is Fun";
var to = new EmailAddress(toEmail);
var plainTextContent = "and easy to do anywhere, even with C#";
var htmlContent = "<strong>and easy to do anywhere, even with C#</strong>";
var msg = MailHelper.CreateSingleEmail(from, to, subject, plainTextContent, htmlContent);
msg.AddHeader("category", "cat1"); //This line does nothing!
var response = await client.SendEmailAsync(msg);
}
}
Thanks Kami, I tried your answer and it worked properly.
I replaced this line msg.AddHeader("category", "cat1"); with msg.AddCategory("cat1");

Error "Bad format of conversation ID"(skype) when send message from skype to direct

Why I have error Bad format of conversation ID(skype) when send message from skype to direct.
IMessageActivity msg = context.MakeMessage();
msg.ChannelId = user.ChannelId;
msg.ServiceUrl = user.serviceUrl;
msg.Recipient = new ChannelAccount(id: user.userID);
msg.Conversation = new ConversationAccount(id: user.conversationId);
msg.Text = textMsg.Text; await context.PostAsync(msg);
I use context.send(), I must use
var connector = new ConnectorClient(new Uri(msg.ServiceUrl), ConfigurationManager.AppSettings["MicrosoftAppId"], ConfigurationManager.AppSettings["MicrosoftAppPassword"]);
await connector.Conversations.SendToConversationAsync((Activity)msg);

Categories

Resources