I have scheduling mail using 'send_at' with future time. Now I want to cancel that scheduled mail. How can achieve this problem. Please provide the solutions for it.
Thanks in advance.
Turns out that you can cancel scheduled email in sendgrid.
Here are the docs on how to do so
Mainly.. "Scheduled sends can be cancelled, if you include a batch ID with your send. "
The docs show you how to add the batch ID to your outbound messages so you can cancel them in the future.
As per the documentation, you cannot cancel scheduled messages at this time: https://sendgrid.com/docs/API_Reference/SMTP_API/scheduling_parameters.html
This can be doable , by creating and assigning batchid in request
Create batch ID,
var batchId="";
var client = new SendGridClient(apikey);
var response = await client.RequestAsync(method:
SendGridClient.Method.POST, urlPath: "mail/batch");
if (response.StatusCode == HttpStatusCode.Created)
{
JObject joResponse = JObject.Parse(response.Body.ReadAsStringAsync().Result);
batchId = (((Newtonsoft.Json.Linq.JValue)joResponse["batch_id"]).Value).ToString();
}
return batchId;
Added batchId in Message body
var msg = new SendGridMessage()
{
From = new EmailAddress("youremail#abc.com", ""),
Subject = subject,
PlainTextContent = message,
HtmlContent = message,
BatchId=batchId
};
var offset = new DateTimeOffset(timeToSend.Value);
long sendAtUnixTime = offset.ToUnixTimeSeconds();
msg.SendAt = sendAtUnixTime;
msg.AddTo(new EmailAddress("recipientmail#abc.com"));
var response = await client.SendEmailAsync(msg);
3)Cancel a scheduled batch
var batchId="yur batch id"
var client = new SendGridClient(apiKey);
string data = "{\"batch_id\":\"" + batchId +"\",\"status\": \"cancel\"}";
var response = await client.RequestAsync(method: SendGridClient.Method.POST,
urlPath: "user/scheduled_sends", requestBody: data);
Note:
Make sure your api key has full access using sender grid option.
Setting --> apiKeys ---> edit Api key--> select "full access" and update
When a batch is canceled, all messages associated with that batch will stay in
your sending queue. When their send at value is reached, they will be discarded.
for more detail please refer enter link description here
Related
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
I'm trying to create code that will send an email using addresses from a specific column in google sheets. I want the code to send an email after the sheet is edited by other users. For example, someone enters a request on a row in the sheet - then an email is sent to the manager of the request. Here's what I have so far...
function SendEmail(){
// Fetch the email address
var emailRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("HLP REQUESTS").getRange("K:K");
var emailAddress = emailRange.getValues()[0][0];
// Send Alert Email.
var message = 'A request has been submitted for professional learning related to an HLP you champion. Please check the Design Team Notes document in case follow-up is required.'; // Second column
var subject = 'HLP Request for Professional Learning';
MailApp.sendEmail(emailAddress, subject, message);
}
When I run the code above I get an error - Exception: Failed to send email: no recipient. There is a valid email address in column K, so I'm a little confused.
If you want get email address from the last cell of the column K it can be done this way:
function SendEmail(){
var emailRange = SpreadsheetApp.getActiveSpreadsheet()
.getSheetByName("HLP REQUESTS").getRange("K:K");
var emailAddress = emailRange.getValues()
.flat() // convert a 2d array into a flat array
.filter(String) // remove empty elements from the array
.pop(); // get the last element from the array
var message = 'A request has been submitted for professional learning related to an HLP you champion. Please check the Design Team Notes document in case follow-up is required.';
var subject = 'HLP Request for Professional Learning';
MailApp.sendEmail(emailAddress, subject, message);
}
Update
Here is the full implementation with installable trigger onEdit that sends email as soon as the checkbox (in column L) was checked in:
// global variables
var SS = SpreadsheetApp.getActiveSpreadsheet(); // get the srpreadsheet
var checkbox_col = 12; // column with checkboxes (L in this case)
// the main function
function sendEmail(e) {
try {
var {rowStart, columnStart} = e.range; // get row and column of the cell that was edited
if (columnStart != checkbox_col) return; // do nothing if it was not column with checkboxes
if (e.value != 'TRUE') return; // do nothing if the checkboxs was unchecked
e.range.setValue(false); // else uncheck the chekbox
var sheet = SS.getSheetByName('HLP REQUESTS'); // get the sheet
var emailAddress = sheet.getRange('K' + rowStart).getValue(); // get email addres from current row, column K
var message = 'A request has been submitted for professional learning related to an HLP you champion. Please check the Design Team Notes document in case follow-up is required.';
var subject = 'HLP Request for Professional Learning';
MailApp.sendEmail(emailAddress, subject, message); // send the message
SS.toast('Email to ' + emailAddress + ' has been sent');
}
catch(e) { SpreadsheetApp.getUi().alert(e) }
}
// additional functions -------------------------------------------------------------------------
// insatll the trigger
function install_onEidt_trigger() {
ScriptApp.newTrigger('sendEmail').forSpreadsheet(SS).onEdit().create();
SS.toast('Trigger was installed');
}
// remove all triggers
function remove_all_triggers() {
ScriptApp.getProjectTriggers().forEach(t => ScriptApp.deleteTrigger(t));
SS.toast('All triggers were remoded');
}
// custom menu to install and remove triggers
function onOpen() {
SpreadsheetApp.getUi().createMenu('⚙️ Scripts')
.addItem('Install trigger', 'install_onEidt_trigger')
.addItem('Remove all triggers', 'remove_all_triggers')
.addToUi();
}
To make it work you have:
to reload the spreadsheet (or to run the function onEdit() manually) to get the custom menu Scripts
in the custom menu run the item Install trigger
after that it will try to send the message to the address from column K of current row whenever user clicks on checkbox in column L
My test sheet looks like this:
Sending Emails
function SendEmail() {
const ss = SpreadsheetApp.getActive();
const rsh = ss.getSheetByName("HLP REQUESTS");
const emails = rsh.getRange("K1:K" + rsh.getLastRow()).getDisplayValues().flat();
var message = 'A request has been submitted for professional learning related to an HLP you champion. Please check the Design Team Notes document in case follow-up is required.';
var subject = 'HLP Request for Professional Learning';
emails.forEach(e => {
MailApp.sendEmail(e, subject, message);
});
}
If you wish to attach this to an onEdit you will have to rethink the process because the onEdit trigger fires on every edit to any sheet and most likely you will be require to use an installable onEdit so that you can perform operations that require permission. I'd recommend you play around with the onEdit simple trigger for a while. Look at the event object and see what's available at low overhead cost.
I have QnA Maker chatbot. I want to do that: If bot gives the DefaultNoAnswer 3 times in a session, I want to show different DefaultNoAnswer. How can I count the DefaultNoAnswers in QnAMakerBaseDialog ?
ex:
Client: asdaaasd
Bot: Sorry, Could you phrase your question differently?
Client: dsjhdsgjdsa
Bot:Sorry, Could you phrase your question differently?
Client: aasdjhajds
Bot: Sorry, I couldn't get the question. Send an email for detailed information.
I find the best way to handle this is with a conversation state variable. I have my default message set up in my helper (i.e. I have a helper file that makes the call to QnA Maker, checks the confidence, and sends a default message in case of low confidence or no answer). If you are using a similar case, you can increment your state variable there. If you are using QnA Maker's default answer directly, you still need to do some check on every result before sending the response to user. I haven't used that method, but I would probably just check the result for the default answer and increment the variable accordingly.
Here is a sample for the first case. I am assuming here that you are already familiar with managing user and conversation state.
var qnaResult = await QnAServiceHelper.queryQnaService(query, oldState);
if (qnaResult[0].score > MINIMUM_SCORE) {
const conversationData = await this.dialogState.get(step.context, {});
conversationData.defaultAnswerCounter = 0;
await this.conversationState.saveChanges(step.context);
var outputActivity = MessageFactory.text(qnaResult[0].answer);
} else {
const conversationData = await this.dialogState.get(step.context, {});
conversationData.defaultAnswerCounter += 1;
if (conversationData.defaultAnswerCounter <= 2) {
var outputActivity = defaultAnswer;
} else {
var outputActivity = escalationAnswer;
}
await this.conversationState.saveChanges(step.context);
}
I want my bot to be able to send some replies later. Like in alarm clock, when user says, ping me at 5 AM then I want to send message to the user at 5 AM. How can I send message without receiving one?
You'll need to receive at least one message so that you know the recipient's address. You'll need to save the addressing info from the incoming message. I think the easiest way is to save the whole message.
Nodejs:
var reply = session.message; // address: reply.address
// ...
reply.text = 'Wake up!';
bot.send(reply);
C#:
var reply = activity.CreateReply(""); // reply.Recipient, reply.Conversation, etc.
// ...
reply.Text = "Wake up!";
ConnectorClient connector = new ConnectorClient(new Uri(reply.ServiceUrl));
await connector.Conversations.ReplyToActivityAsync(reply);
Without reply to an activity request, you can send a message to him like the following. I should mention that you must have the user's Id, and it means at least the user should have sent a message to the bot, to store his id.
string userId ="123456789"; // For Example
string serviceUrl = "https://telegram.botframework.com"; // For Example
var connector = new ConnectorClient(new Uri(serviceUrl));
IMessageActivity newMessage = Activity.CreateMessageActivity();
newMessage.Type = ActivityTypes.Message;
newMessage.From = new ChannelAccount("<BotId>", "<BotName>");
newMessage.Conversation = new ConversationAccount(false, userId);
newMessage.Recipient = new ChannelAccount(userId);
newMessage.Text = "<MessageText>";
await connector.Conversations.SendToConversationAsync((Activity)newMessage);
The above code comes from here.
I'm trying to delete a user-to-user request using facebook-actionscript-api. So far no success..I've tried the following codes:
//try #1
var data:Object = new Object();
data.method = 'delete';
var userid:String = "idOfTheRequestSender"; //id of the request sender
var fullrequestID:String = requestId + '_'+ userid;//requestId - id of the sent request
Facebook.api(fullrequestID, onRequestDeleteCallBack, data, "POST");
//try #2
var userid:String = "idOfTheRequestSender"; //id of the request sender
var fullrequestID:String = requestId + '_'+ userid; //requestId - id of the sent request
Facebook.deleteObject(fullrequestID, onRequestDeleteCallBack);
I am replacing the userid with what it should be in my app.
Neither works as the callback function parameter is always null and the request is not deleted. Any help would be appreciated.Thanks.
The problem is just deleting the requests, i am able to send them.
EDIT:
The problem was that i was trying to delete the request from the Facebook account that sent the request, not from the account that received the request. Now it works. Thanks.
Did you try :
Facebook.api(fullrequestID, onRequestDeleteCallBack, {}, "DELETE");
Also are you getting any error messages?