Delay in sending email in ASP.NET CORE - asp.net-core

Hi am building a web application using blazor which sends email activation link to registered users, email activation is is being sent but the problem here it takes too long(approximately 5 minutes) for the registered user to receive the activation link. here is my code.
my interface class
public interface IEmailServices
{
Task SendEmailAsync(string toAddress, string subject, string body);
}
My mail Sender Class
public class EmailSender : IEmailServices
{
public async Task SendEmailAsync(string emailDestination, string subject, string htmlMessageBody )
{
MailMessage ms = new MailMessage("myemail#domain.com", emailDestination, subject,htmlMessageBody);
ms.IsBodyHtml = true;
string user = "myemail#domain.com";
string passcode = "mypassword";
SmtpClient smtpServer = new SmtpClient("mail.domain.com");
smtpServer.Credentials = new System.Net.NetworkCredential(user, passcode);
try
{
await smtpServer.SendMailAsync(ms);
}
catch (Exception ex)
{
throw ex;
}
}
}
Here's where am sending the message
//Generate Email confirmation link
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
var callbackUrl = Url.Page(
"/Account/ConfirmEmail",
pageHandler: null,
values: new { area = "Identity", userId = user.Id, code = code },
protocol: Request.Scheme);
await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",
$"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
I want the message to be sent immediately upon registration so user can confirm email.. is there something am missing thanks in advance

You don't appear to be doing anything that would generate a huge email, so this shouldn't be taking very long. A suggestion I can make is to set up your app in a test environment, with the SMTP connection set to an email account you have access to in your configuration. (Even a gmail account would work, but you'd have to set the Gmail security appropriately.) Then, run your app in debug mode with a breakpoint at await smtpServer.SendMailAsync(ms);, and then continue (F5 in VS) forward from that call to execute SendEmail Async() and let the app continue running. This will allow confirmation that the email sent, and also give you some insight into if the issue is ahead of sending the email entirely or not. Make sure you are signed in to the email account you are testing with before you start, then hop into the email account Sent folder and check that it shows the sent email. If the email takes a long time to send, the issue is in your SMTP connection from the app. If it sends in short order but still takes forever to arrive at the recipient, it has to do with the email account(s) or the clients hooked up to them (think the Send / Receive interval in Outlook set too long), but not necessarily your application. That should help you pin the problem down so you know what you are dealing with.

Related

How to send email from any one email using Microsoft Graph

I am using microsoft graph to send email. This email I want to send from any email that exists in the Active directory.
I already have get the permission on Mail.Send and have admin consent on Azure.So all set on the Azure level for access and permission.
Now when come to code. I have searched for but I am not able to figure out how to call the Microsoft graph api to send the email. Below is the code that I have been finding when I am doing search. How I can replace the below code to send the email to anyone from anyone in Azure AD to anyone in Azure AD. Also the code for send email 'Send AS'.
await graphClient.Me.Messages
.Request()
.AddAsync(message);
The intention is the signed in user will not send email from his email
address, the email notification will be asthmatically sent by someone
else name to someone.
Then I think you wanna provide a sending email to your users, users can choose who received the email, but all the email should be sent be a specific account, such as admin#xxx.onmicrosoft.com, then you should know something about the sending email api.
As #user2250152 mentioned, await graphClient.Users["userId"], here the userId means who send the email, as your requirement is sending all emails from one specific email address, it should hardcode as admin#xxx.onmicrosoft.com.
The next is how to send the email, calling ms graph api should offer an access token, as your requirement is sending email by the application but not every user, so I'm afraid the client credential flow is a better choice so that when the scenario comes to sending email from several specific email addresses, you don't need to change the flow then. Now you need to require your tenant admin to add Mail.Send Application api permission in azure ad to use this kind of flow.
And here's the code:
using Azure.Identity;
using Microsoft.Graph;
var mesg = new Message
{
Subject = "Meet for lunch?",
Body = new ItemBody
{
ContentType = BodyType.Text,
Content = "The new cafeteria is open."
},
ToRecipients = new List<Recipient>
{
new Recipient
{
EmailAddress = new EmailAddress
{
//who will receive the email
Address = "xxx#gmail.com"
}
}
},
Attachments = new MessageAttachmentsCollectionPage()
};
var scopes = new[] { "https://graph.microsoft.com/.default" };
var tenantId = "your_tenant_name.onmicrosoft.com";
var clientId = "azure_ad_app_client_id";
var clientSecret = "client_secret_for_the_azuread_app";
var clientSecretCredential = new ClientSecretCredential(
tenantId, clientId, clientSecret);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
await graphClient.Users["user_id_which_you_wanna_used_for_sending_email"].SendMail(mesg, false).Request().PostAsync();
You can send mail from other user this way.
var message = new Message
{
Subject = "Subject",
Body = new ItemBody
{
ContentType = BodyType.Text,
Content = "Content"
},
ToRecipients = new List<Recipient>()
{
new Recipient
{
EmailAddress = new EmailAddress
{
Address = "john.doe#contoso.onmicrosoft.com"
}
}
}
};
var saveToSentItems = false;
await graphClient.Users["userId"]
.SendMail(message,saveToSentItems)
.Request()
.PostAsync();
userId is the unique identifier for the user. Instead of userId you can use userPrincipalName. The UPN is an Internet-style login name for the user based on the Internet standard RFC 822. By convention, this should map to the user's email name.
Resources:
Send mail
User resource

Is it possible to have a different sender email and configuration email to send email from MimeKit in ASP.Net Core?

I have added code which will send emails to the receiving party. As of now I need to add the same email address in "from" email and "username"(config email) to send the email else it will fail. But I wish to have different "from" email and not asking users for password and using one config mail to send email so multiple users can consume this service to send emails. Is it possible to do so?
Here is my code:
public async Task<string> Send(string from, string to, string subject, string html, string userName, string password)
{
// create message
var email = new MimeMessage();
email.From.Add(MailboxAddress.Parse(from));
email.To.Add(MailboxAddress.Parse(to));
email.Subject = subject;
email.Body = new TextPart(TextFormat.Html) { Text = html };
using var smtp = new SmtpClient();
smtp.Connect("smtp.live.com", 587, SecureSocketOptions.StartTls);
smtp.Authenticate(userName, password);
smtp.Send(email);
smtp.Disconnect(true);
return "Email Set";
}
Yes, but you'll need to use a private SMTP server that will accept different addresses in the From: header and the authenticate commands. None of the widely-used public SMTP servers allow this as far as I know.

Bot api, how i can get last message or chat history?

I want implement some functional like user send me a message and I reply to him with my (bot) latest message from chat history.
As you can see in the Telegram Bot API Documentation you can use sendMessage to send a message to the user.
When you receive a message, look for the chat or the from parameter in the JSON (depends if you want to answer to the person when it's a group chat or not). You can use the id parameter of the chat or from to send the message.
So the first parameter for your sendMessage would be chat_id=message.chat.id
You don't need the parse_mode, disable_web_page_preview and reply_markup for this example.
As you want to reply to the message of the user you may want to set the reply_to_message_id to the id of the received message.
reply_to_message_id = message.message_id
Last but not least, you want to set the text parameter. If I understand it correctly, your program will send the last received message.text to the user.
So what you want to do is, as soon as you get a message, save it.
Message oldMessage = message
And when you send the Message to the user use the old messages text property as the text.
text = oldMessage.text
Alright to sum it up here is the pseudocode of the function that will happen as soon as you receive a message:
Message oldMessage = null;
public void NewMessage(Message message){
int chat_id = message.chat.id;
int reply_to_message_id = message.message_id;
String text = "There is no old Message"; //fallback value
if(oldMessage != null){
text = oldMessage.text;
}
//Send Message in this example only has 3 parameters, and ignores the
//not used ones
SendMessage(chat_id,text,reply_to_message_id);
oldMessage = message; //store the received message for future answering
}
As you store the whole message in oldMessage you could also set the text you will send to something like this:
String text = oldMessage.from.first_name+": "+oldMessage.text;
if you simply want to reply on users message you need this function:
public void sendMsg(Message message, String text){
SendMessage sendMessage = new SendMessage();
sendMessage.enableMarkdown(true);
sendMessage.setChatId(message.getChatId().toString());
sendMessage.setReplyToMessageId(message.getMessageId());
sendMessage.setText(text);
try{
setButtons(sendMessage);
sendMessage(sendMessage);
}catch (TelegramApiException e){
e.printStackTrace();
}
}

Custom User login in AppEngine

I have a Java Servlet backend with a datastore connected to my app; I am trying to implement a login system using the Android Studio LoginActivity template, using the user's email and password (not the PlusBaseActivity handling the Google Account login), but I don't know how to proceed from here:
How can you say that a User is logged in? and how can I make it so persistently using my datastore? I've read here: How to login User using UserService on AppEngine Java that I just need to call the method resp.sendRedirect(userService.createLoginURL(req.getRequestURI())), and I've done so:
#Override
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
int size = checkDatastore(); // 0 if empty, > 0 if not empty
if(size==0){
populateDatastore();
}
String asyncMessage = req.getParameter("order");
if(asyncMessage.equals("login")){
mail = req.getParameter("email");
psw = req.getParameter("password");
UserService userService = UserServiceFactory.getUserService();
User user = userService.getCurrentUser();
String message="";
resp.setContentType("text/plain");
PrintWriter out = resp.getWriter();
if(user == null) {
//Sends a temporary redirect response to the client using the
// specified redirect location URL and clears the buffer.
String uri = userService.createLoginURL(req.getRequestURI());
resp.sendRedirect(uri);
User user1 = userService.getCurrentUser();
message="No one is logged in!\n" + "Sent from App Engine at " + new Date();
out.println(message);
out.flush();
}if(user !=null) {
// login(user);
message = "Hello, " + user.getEmail() +
", "+user.getNickname()+"!" + "\nSent from App Engine at "+ new Date();
out.println(message);
out.flush();
}
}
}
but the sendRedirect() method only gives me a URI. What for?
Moreover, the User user = userService.getCurrentUser() always returns null. How come?
That's because the resp.sendRedirect(userService.createLoginURL(req.getRequestURI()))
of UserService only works when integrating the Login with Google Accounts as shown in this documentation.
If you want to implement a personalised login system you can do that in many ways. Surely you will need a Servlet checking new users' data and a datastore to persistently store new account registrations.

SMStextmesage background service async

The following code will work for CLICK event handler but i cant let it send automatically
async void Button_Click_1(object sender, RoutedEventArgs e)
{
SmsDevice smsDevice2 = (SmsDevice)await SmsDevice.GetDefaultAsync();
// Create a text message - Set destination number and message text
SmsTextMessage msg = new SmsTextMessage();
msg.To = "12345678";
msg.Body = "xxxx";
// Send the message asynchronously
await smsDevice2.SendMessageAsync(msg);
}
This wont work (background service)
async void DisplayToastAsync(IBackgroundTaskInstance taskInstance, ManualResetEvent manualEventWaiter)
{
SmsDevice smsDevice2 = (SmsDevice)await SmsDevice.GetDefaultAsync();
// Create a text message - Set destination number and message text
SmsTextMessage msg = new SmsTextMessage();
msg.To = "12345678";
msg.Body = "xxx";
// Send the message asynchronously
await smsDevice2.SendMessageAsync(msg);
}
Anyone know why? and how can i fix it?
I was experimenting and I found that you do need to fill in the "From" field (a copy of SmsDevice.AccountPhoneNumber).
Having said that, I still get a so called 'generic error', but at least it isn't a 'parameter error'.
If you're interested, my generic error is 0x80548212.
Also - I'm guessing you already did this (or I think you'd get a null sms device )- but you need to make the app as being able to do text messaging in the manifest.
Further info - that Generic Error was that my SIM was enabled for Data only. Once swapped out for a SIM that included SMS, the code worked fine.