I wrote the following .net code to add run time email address in AWS-SES "Email Address Identities list" and sending email to user for verification, but its not working, though the response saying "WaitingforActivation". But neither email address is added in SES "Email Address Identities" nor email went to the respective email address for verification. Any help on the same is appreciated.
public void SESVerifyEmailIdentity()
{
var sesClient = new AmazonSimpleEmailServiceClient("XXXXXXXXXXXXX", "XXXXXXXXXXX", "USEast1");
var request = new VerifyEmailIdentityRequest
{
EmailAddress = "Joe#example.com"
};
var response = sesClient.VerifyEmailIdentityAsync(request);
}
I resolved my issue, I was not using the right credentials for AWS. When I used my AWS credentials, its working for me.
public void SESVerifyEmailIdentity()
{
#region SESVerifyEmailIdentity
var awsCredentials = new
Amazon.Runtime.BasicAWSCredentials("YOUR-ACCESS-KEY-HERE", "YOUR-SECRET-KEY-HERE);
var sesClient = new AmazonSimpleEmailServiceClient(awsCredentials, RegionEndpoint.USEast1);
var request = new VerifyEmailIdentityRequest
{
EmailAddress = "Joe#Example.com"
};
var response = sesClient.VerifyEmailIdentityAsync(request);
#endregion
}
Related
I have an endpoint that subscribes the specified email to my SNS topic:
[HttpPost("subscriptions/{email}")]
public async Task SubscribeEmail(string email)
{
try
{
var request = new SubscribeRequest()
{
TopicArn = AwsServicesConstants.SenderTopicArn,
ReturnSubscriptionArn = true,
Protocol = "email",
Endpoint = email,
};
var response = await _snsClient.SubscribeAsync(request);
}
catch (Exception ex)
{
Console.WriteLine($"Unexpected error: {ex}");
}
}
How can I unsubscribe given email from that topic with just a specified email like this
[HttpDelete("subscriptions/{email}")]
public async Task<UnsubscribeResponse> UnsubscribeEmail(string email)
{
var request = new UnsubscribeRequest(email);
var response = await _snsClient.UnsubscribeAsync(request);
return response;
}
Actually, unsubscription is not working because UnsubscribeRequest requires only subscriptionArn, and not the email
You will need to identify the subscription (once subscribed) by calling ListSubscriptionsByTopic, looking for the Endpoint that matches the desired email address. You could then extract the ARN and use it when calling Unsubscribe.
You can write app logic to get the ARN value using the email address. Here is a C# example that shows you the logic for this use case using the AWS SDK for .NET.
public async Task<string> UnSubEmail(string email)
{
var client = new AmazonSimpleNotificationServiceClient(RegionEndpoint.USEast2);
var arnValue = await GetSubArn(client, email);
await RemoveSub(client, arnValue);
return $"{email} was successfully deleted!";
}
public static async Task<string> GetSubArn(IAmazonSimpleNotificationService client, string email)
{
var request = new ListSubscriptionsByTopicRequest();
request.TopicArn = TopicArn;
var subArn = string.Empty;
var response = await client.ListSubscriptionsByTopicAsync(request);
List<Subscription> allSubs = response.Subscriptions;
// Get the ARN Value for this subscription.
foreach (Subscription sub in allSubs)
{
if (sub.Endpoint.Equals(email))
{
subArn = sub.SubscriptionArn;
return subArn;
}
}
return string.Empty;
}
public static async Task<string> RemoveSub(IAmazonSimpleNotificationService client, string subArn)
{
var request = new UnsubscribeRequest();
request.SubscriptionArn = subArn;
await client.UnsubscribeAsync(request);
return string.Empty;
}
You can find full .NET Example in the AWS Code Lib:
Build a publish and subscription application that translates messages
I have gmail API service account details = client id and service account. How can I just send an email from one id to other without OAuth?
I want to authorize this email sending process with the service account credentials only.
Is there a nuget package that can help fulfill this requirement?
How can I just send an email from one id to other without OAuth?
I assume what you mean is how to send an email with out poping up the Oauth2 consent screen.
Using a service account will allow you to do that, once you have configured the permissions properly in your google workspace account. You grant the service account to preform actions on behalf of one of your domain users. This way the service account can send emails as that user without the user having to consent to that access because you have pre authorized it via google workspace.
The following code will show you how to authorize your application to use a service account.
class Program
{
public static string Base64Encode(string plainText)
{
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
return System.Convert.ToBase64String(plainTextBytes);
}
public static void SendMail()
{
try
{
string ApplicationName = "Gmail API .NET Quickstart";
const string serviceAccount = "xxxx#xxxx-api.iam.gserviceaccount.com";
var certificate = new X509Certificate2(#"c:\XXXX.p12", "notasecret", X509KeyStorageFlags.Exportable);
var gsuiteUser = "YourDomain#YourDomain.com";
var serviceAccountCredentialInitializer = new ServiceAccountCredential.Initializer(serviceAccount)
{
User = gsuiteUser,
Scopes = new[] { GmailService.Scope.GmailSend, GmailService.Scope.GmailLabels }
}.FromCertificate(certificate);
var credential = new ServiceAccountCredential(serviceAccountCredentialInitializer);
if (!credential.RequestAccessTokenAsync(CancellationToken.None).Result)
throw new InvalidOperationException("Access token failed.");
var service = new GmailService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName,
});
var mailMessage = new MailMessage();
mailMessage.From = new MailAddress("se#Yourdomain.com");
mailMessage.To.Add("ddddd#hotmail.com");
mailMessage.ReplyToList.Add("se#Yourdomain.com");
mailMessage.Subject = "test";
mailMessage.Body = "<h1>sdf</h1>";
mailMessage.IsBodyHtml = true;
//foreach (System.Net.Mail.Attachment attachment in email.Attachments)
//{
// mailMessage.Attachments.Add(attachment);
//}
var mimeMessage = MimeKit.MimeMessage.CreateFromMailMessage(mailMessage);
var gmailMessage = new Message
{
Raw = Base64Encode(mimeMessage.ToString())
};
Message message1 = new Message();
UsersResource.MessagesResource.SendRequest sendRequest = service.Users.Messages.Send(gmailMessage, "me");
var s = sendRequest.Execute();
Console.WriteLine("Message delivered!");
}
catch (Exception ep)
{
Console.WriteLine(ep.ToString());
}
}
The trick is to remember to set up the domain wide delegation properly and to decide which user the service account is going to be impersonating and to remember to add that email
without google workspace
If you do not have a google workspace account then you can not use service accounts. You may want to consider going though the smtp server instead.
So I am trying to implement password recovery in ASP.NET Web application but something is wrong.
I am using this code -
public class EmailService : IIdentityMessageService
{
public async Task SendAsync(IdentityMessage message)
{
await configSendGridasync(message);
}
// Use NuGet to install SendGrid (Basic C# client lib)
private async Task configSendGridasync(IdentityMessage message)
{
var myMessage = new SendGridMessage();
myMessage.AddTo(message.Destination);
myMessage.From = new MailAddress(
"mymail#gmail.com", "Joe S.");
myMessage.Subject = message.Subject;
myMessage.PlainTextContent = message.Body;
myMessage.HtmlContent = message.Body;
var credentials = new NetworkCredential(
ConfigurationManager.AppSettings["mailAccount"],
ConfigurationManager.AppSettings["mailPassword"]
);
// Create a Web transport for sending email.
var transportWeb = new Web(credentials);
// Send the email.
if (transportWeb != null)
{
await transportWeb.DeliverAsync(myMessage);
}
else
{
Trace.TraceError("Failed to create Web transport.");
await Task.FromResult(0);
}
}
}
But
myMessage.From = new MailAddress(
"mymail#gmail.com", "Joe S.");
Is giving error cs0029 Cannot implicitly convert type system.Net.MailAdress to SendGrid.Helpers.Mail.Adress
Also, in line var transportWeb = new Web(credentials); Web is not found.
Do any have idea what is wrong ?
SendGrid Nuget package is installed.
Your code is picking up MailAddress from the System.Net namespace. You need to resolve this from the SendGrid.Helper.Mail namespace instead.
Or you are creating MailAddress when you should be passing Address;
There are a number of ways to achieve this, most simply;
myMessage.From = new SendGrid.Helpers.Mail.Address("mymail#gmail.com", "Joe S.");
Looking at the SendGrid docs you might also want to consider using EmailAddress instead of MailAddress or Address.
https://sendgrid.com/docs/for-developers/sending-email/v3-csharp-code-example/
var to = new EmailAddress("test#example.com", "Example User");
I have an asp.net 4.6 web forms application (no MVC). I am updating the security in my application. I am using OpenIdConnectAuthentication to authenticate with our Azure AD. Then I pass the access token to Microsoft graph to send an email with Office 365. My token is set to expire in 60 minutes. I either need to expand the expiration to 8 hours or refresh the token. Without having MVC I am not sure how to handle this. I am looking for help with direction to take and possibly code samples.
(I original tried to utilize an MVC sample and put it into my project using a Session Token class. Once we tested with multiple users I believe I had a memory leak and it would crash in about 5 minutes.)
Startup code:
public class Startup
{
private readonly string _clientId = ConfigurationManager.AppSettings["ClientId"];
private readonly string _redirectUri = ConfigurationManager.AppSettings["RedirectUri"];
private readonly string _authority = ConfigurationManager.AppSettings["Authority"];
private readonly string _clientSecret = ConfigurationManager.AppSettings["ClientSecret"];
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
}
public void ConfigureAuth(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
CookieManager = new SystemWebCookieManager(),
});
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
ClientId = _clientId,
ClientSecret = _clientSecret,
//Authority = _authority,
Authority = String.Format(_authority, domain, "/v2.0"),
RedirectUri = _redirectUri,
ResponseType = OpenIdConnectResponseType.CodeIdToken,
Scope = OpenIdConnectScope.OpenIdProfile,
UseTokenLifetime = false,
TokenValidationParameters = new TokenValidationParameters { NameClaimType = "name", RequireExpirationTime = false},
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthorizationCodeReceived = async n =>
{
// Exchange code for access and ID tokens
var auth = String.Format(_authority, "common/oauth2/v2.0", "/token");
var tokenClient = new TokenClient($"{auth}", _clientId, _clientSecret);
var tokenResponse = await tokenClient.RequestAuthorizationCodeAsync(n.Code, _redirectUri);
if (tokenResponse.IsError)
{
throw new Exception(tokenResponse.Error);
}
var claims = new List<Claim>()
{
new Claim("id_token", tokenResponse.IdentityToken),
new Claim("access_token", tokenResponse.AccessToken)
};
n.AuthenticationTicket.Identity.AddClaims(claims);
},
},
});
}
}
SDK Helper:
public class SDKHelper
{
// Get an authenticated Microsoft Graph Service client.
public static GraphServiceClient GetAuthenticatedClient()
{
GraphServiceClient graphClient = new GraphServiceClient(
new DelegateAuthenticationProvider(
async (requestMessage) =>
{
string accessToken = System.Security.Claims.ClaimsPrincipal.Current.FindFirst("access_token").Value;
// Append the access token to the request.
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", accessToken);
// Get event times in the current time zone.
requestMessage.Headers.Add("Prefer", "outlook.timezone=\"" + TimeZoneInfo.Local.Id + "\"");
// This header has been added to identify our sample in the Microsoft Graph service. If extracting this code for your project please remove.
requestMessage.Headers.Add("SampleID", "aspnet-snippets-sample");
}));
return graphClient;
}
}
Sending Email:
GraphServiceClient graphClient = SDKHelper.GetAuthenticatedClient();
string address = emailaddress;
string guid = Guid.NewGuid().ToString();
List<Recipient> recipients = new List<Recipient>();
recipients.Add(new Recipient
{
EmailAddress = new Microsoft.Graph.EmailAddress
{
Address = address
}
});
// Create the message.
Message email = new Message
{
Body = new ItemBody
{
ContentType = Microsoft.Graph.BodyType.Text,
},
Subject = "TEST",
ToRecipients = recipients,
From = new Recipient
{
EmailAddress = new Microsoft.Graph.EmailAddress
{
Address = address
}
}
};
// Send the message.
try
{
graphClient.Me.SendMail(email, true).Request().PostAsync().Wait();
}
catch (ServiceException exMsg)
{
}
You need to request the scope offline_access. Once you've requested that, the /token endpoint will return both an access_token and a refresh_token. When your token expires, you can make another call to the /token endpoint to request a new set of access and refresh tokens.
You might find this article helpful: Microsoft v2 Endpoint Primer. In particular, the section on refresh tokens.
I'm trying to integrate the OneDrive for Busines to a Web Form App.
For this I use the documentation given at this url
In web Form App I have two Pages:
First one is Login page which have a button for login
On login button click I create a GET Request to OneDrive for Business API using the following code:
HttpClient client = new HttpClient();
Redirecturi = Uri.EscapeDataString(Redirecturi);
string url = string.Format("https://login.windows.net/common/oauth2/authorize?response_type=code&client_id={0}&redirect_uri={1}", ClienId, Redirecturi);
var response = client.GetAsync(url);
var json = response.Result.Content.ReadAsStringAsync();
Label2.Text = json.Result;
When I click the login button it takes me to micorosoft login service and sends me back to callback.aspx page with access code (Redirect URI configured on azure)
I got the access code.
On the second page I redeem the access code and make a POST request to get the Authentication token.
Here is the code for the second page:
private string BaseUri="https://login.windows.net/common/oauth2/token";
public string Redirecturi = "http://localhost:51642/CallBack.aspx";
public string ResourcesId = "https://api.office.com/discovery/";
private string ClienId = "180c6ac4-5829-468e-.....-822405804862"; ///truncated//azure
private string ClientSecert = "G4TAQzD8d7C4...OE6m366afv8XKbTCcyXr4=";//truncated
protected void Page_Load(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(Request.QueryString[OAuthConstants.AccessToken]))
{
// There is a token available already. It should be the token flow. Ignore it.
return;
}
if (!string.IsNullOrEmpty(Request.QueryString[OAuthConstants.Code]))
{
string _accessCode = Request.QueryString[OAuthConstants.Code];
HttpClient client = new HttpClient();
// BaseUri = Uri.EscapeDataString(BaseUri);
Redirecturi = Uri.EscapeDataString(Redirecturi);
ResourcesId = Uri.EscapeDataString(ResourcesId);
string url = string.Format("{0}?client_id={1}&redirect_uri={2}&grant_type=authorization_code&client_secret={3}&code={4}&grant_type=authorization_code&resource={5}", BaseUri, ClienId, Redirecturi, ClientSecert, _accessCode, ResourcesId);
var response = client.PostAsync(url, null);
var json = response.Result.Content.ReadAsStringAsync();
Response.Write(json);
}
}
But instead of Response I am get the following error. Which say include the grant_type in url. I have already added (you can check in code).
I get same error the same error without including it.
Here is the error
{"error":"invalid_request","error_description":"AADSTS90014: The request body must contain the following parameter: 'grant_type'.\r\nTrace ID: 2adb3a7f-ceb1-4978-97c4-3dc2d3cc3ad4\r\nCorrelation ID: 29fb11a0-c602-4891-9299-b0b538d75b5f\r\nTimestamp: 2015-07-15 09:58:42Z","error_codes":[90014],"timestamp":"2015-07-15 09:58:42Z","trace_id":"2adb3a7f-ceb1-4978-97c4-3dc2d3cc3ad4","correlation_id":"29fb11a0-c602-4891-9299-b0b538d75b5f","submit_url":null,"context":null}
Please help to know where or what is getting wrong.
Any kind of help will be appreciable
You're adding the parameters to the request querystring. You have to post the data in the request body.
var content = new StringContent(
"grant_type=authorization_code" +
"&client_id=" + ClienId +
"&redirect_uri=" + Redirecturi +
"&client_secret=" + ClientSecert +
"&code=" + _accessCode +
"&resource=" + ResourcesId,
Encoding.UTF8,
"application/x-www-form-urlencoded");
var response = httpClient.PostAsync(BaseUri, content);
var result = response.Result.Content.ReadAsStringAsync();
use FormUrlEncodedContent instead of StringContent (form data post)
var formContent = new FormUrlEncodedContent(new Dictionary<string, string>
{
{ "client_id", clientId },
{ "client_secret", clientSecret },
{ "code", authCode },
{ "redirect_uri", redirectUri },
{ "grant_type", "authorization_code" }
});
var response = await httpClient.PostAsync("https://login.microsoftonline.com/common/oauth2/token", formContent);
Sharing for future readers because this error is not specific to OneDrive only but can arise in other Microsoft tools
I was getting this error when working with Microsoft Bot Framework's Skype bot. In my case the bot file the appId and appSecret was wrongly set to clientId and clientSecret
Changing the same to appId and appSecret fixed the issue.