How to configure spring lemon to send emails via Sendgrid? - spring-lemon

I successfully sent emails via sendgrid's SMTP api, without change to my spring-lemon code. I did it just by configuring environment variables on cloudfoundry.
I would now like to use sendgrid java library
I then created the following class
SendGrid sendgrid = new SendGrid('api_key');
SendGrid.Email email = new SendGrid.Email();
email.addTo("example#example.com");
email.setFrom("other#example.com");
email.setSubject("Hello World");
email.setText("My first email with SendGrid Java!");
try {
SendGrid.Response response = sendgrid.send(email);
System.out.println(response.getMessage());
}
catch (SendGridException e) {
System.err.println(e);
}
How do I get spring-lemon to use this class instead of SmtpMailSender ?

Having your custom implementation of MailSender, and configuring that as a bean should suppress Spring Lemon's SmtpMailSender configuration, because Spring Lemon's MailConfiguration class is annotated with #ConditionalOnMissingBean(MailSender.class). (Refer page 79 of the blueprint book - Allowing developers to provide their implementations)
#ConditionalOnMissingBean is notorious, but I had tested it to be working in this case.

Related

Using generated on the server AccessToken to connect to GCP Text to Speech

I would like to be able to connect to GCP Text to Speech from a react.js front-end using an access token generated on the server. I adapted the code from the linked reply to produce an access token. However, I was not able to find in the docs how to use that token to connect from the front-end to GCP.
For simplicity, I would like to begin with modifying the linked working node.js example from the docs to use the hardcoded access token instead of the Default Credentials File to connect with the service.
Here is my attempt (compared to the example, only the construction of client is modified):
'use strict';
function main() {
// [START tts_quickstart]
// Imports the Google Cloud client library
const textToSpeech = require('#google-cloud/text-to-speech');
// Import other required libraries
const fs = require('fs');
const util = require('util');
// Creates a client
const client = new textToSpeech({tk: 'ya29.c.Kp8BCQj<etc.>'}).TextToSpeechClient();
async function quickStart() {
// The text to synthesize
const text = 'hello, world!';
// Construct the request
const request = {
input: {text: text},
// Select the language and SSML voice gender (optional)
voice: {languageCode: 'en-US', ssmlGender: 'NEUTRAL'},
// select the type of audio encoding
audioConfig: {audioEncoding: 'MP3'},
};
// Performs the text-to-speech request
const [response] = await client.synthesizeSpeech(request);
// Write the binary audio content to a local file
const writeFile = util.promisify(fs.writeFile);
await writeFile('output.mp3', response.audioContent, 'binary');
console.log('Audio content written to file: output.mp3');
}
quickStart();
// [END tts_quickstart]
}
main(...process.argv.slice(2));
I get an error that textToSpeech is not a constructor. How can I fix this example to connect to GCP Text to Speech using the access token?
Unfortunately it is not possible to authenticate via access token using the Text-To-Speech Nodejs Client Library. The TextToSpeechClient in Node runtime only accepts credentials objects which can be found from service accounts.
Based from the SO example you included in your question, it generates the access token and uses it in Android. It makes sense since there are no client libraries for Android as of now, so the OP is using the Text-To-Speech REST API to create an HTTP request. Using HTTP request requires the access token to authenticate, thus the solution of the SO example.
My suggestions are the following:
Adapt the solution similar to the SO example which is sending request via HTTP so you can use access token for authentication.
Use a different programming language like Python (seems unlikely since you are using React). It is possible in Python Client Library to use access token for authentication since it accepts credentials object.
Also just to add you are passing parameters incorrectly on your client object. It should be const client = new textToSpeech.TextToSpeechClient(object);

Unable to send mail via Mailgun over api or smtp

I have setup a new account and not verified my domain. I would like to test and confirm mail-send before proceeding with verification and adding payment information.
I have tried curl using the sandbox method and api key (including smtp). I have also tried to use my domain using the top account mail-address as recipient. But each time the send command (both curl and smtp) I get "Mailgun Magnificent API" response - but no mail is delivered. So far the Mailgun API does not look so Magnificent... I have gone through the documentation multiple times and cannot find what I might be doing wrong..
Any help is much appreciated.
Faced the same issue while sending emails via api by php curl. I solved it by changing API Base URL https://api.mailgun.net/v3/YOUR_DOMAIN_NAME to https://api.mailgun.net/v3/YOUR_DOMAIN_NAME/messages.
It's because their api is not only for sending.
Hope this helps.
For anyone else trying to figure out what "Mailgun Magnificent API" means in a Mailgun HTTP 200-OK API response, it occurs when posting to https://api.mailgun.net/v3/YOUR_DOMAIN_NAME/some/api/endpoint when /some/api/endpoint is not a valid Mailgun API endpoint.
If you are using a client library, there's probably a mistake in your Mailgun sender domain setting. Say you've verified the domain mg.example.com with Mailgun. Examples that can result in "Mailgun Magnificent API" (the exact setting name depends on the library):
MAILGUN_DOMAIN = mg.example.com # comment—this is a common mistake in dotenv files, which don't usually support inline comments; move the # comment to its own line
MAILGUN_DOMAIN = mg.example.com/mysite—get rid of the /mysite part
If you are posting directly to the Mailgun API (or developing a client library), there are some additional ways you might get "Mailgun Magnificent API":
Omitting the API endpoint: https://api.mailgun.net/v3/mg.example.com (as noted in another response)
Misspelling the endpoint: https://api.mailgun.net/v3/mg.example.com/massages (that should be messages with an e)
Including a # or ? after your domain: https://api.mailgun.net/v3/mg.example.com #/messages (see the note above about comments in config files)
Including an extra path after your domain: https://api.mailgun.net/v3/mg.example.com/route/to/my/app/messages
Note that you won't see "Mailgun Magnificent API" if YOUR_DOMAIN_NAME is not a valid sending domain you've registered with Mailgun. (In that case, Mailgun instead responds 404-Not Found).
The mailgun guide shows you to use https://api.mailgun.net/v3/YOUR_DOMAIN as YOUR_DOMAIN_NAME as in the snippet below and this was the problem.
If you're using mailgun-js, you simply need to have YOUR_DOMAIN as YOUR_DOMAIN_NAME.
No need for the https://api.mailgun.net/v3 part
const API_KEY = 'YOUR_API_KEY';
const DOMAIN = 'YOUR_DOMAIN_NAME';
const mailgun = require('mailgun-js')({apiKey: API_KEY, domain: DOMAIN});
const data = {
from: 'Excited User <me#samples.mailgun.org>',
to: 'foo#example.com, bar#example.com',
subject: 'Hello',
text: 'Testing some Mailgun awesomeness!'
};
mailgun.messages().send(data, (error, body) => {
console.log(body);
});
The problem for me was not including my domain name in the url and trying to type everything onto a single line. Strictly following their online example. Typing a backslash will bring your cursor to a new line.
$ curl -s --user 'api:key-xxx' \
https://api.mailgun.net/v3/your_domain/messages \
-F from='User <user#sample.mailgun.org>' \
-F to='xxx#gmail.com' \
-F subject='Hello' \
-F text='Testing some mailgun!'
Response
{
"id": "<xxx.x.xxx#your_domain>",
"message": "Queued. Thank you."
}
Including an slash "/" after messages url part at the end causes this failure too.
For example if you are using a library like Refit for c#, ensure your service interface be declared like this (see the Post attribute):
public interface IMailgunService
{
[Post("")]
Task<JsonDocument> SendEmailAsync([Body(BodySerializationMethod.UrlEncoded)] Dictionary<string, object> data);
}

Generate API client from Django REST framework API

I have an website in Django that is using the REST framework to provide an API.
Is there a way to generate an API client that can be used to communicate with this API that provides objects mapping the contents of the API?
If you're talking about a javascript client API, I have a django management task that I use to generate a javascript library from my DRF API
using AngularJS 1.*. I'm still using DRF 2.4, for easy nested object writes, and Django 1.7. Here it is as a github gist
Take that file, stick it in <app>/management/commands/ and call it like:
python manage.py rest_framework_2_js rest_api.gen.js [base_factory_name] [server_base_url]
If your base_factory_name was foo and you had an API object at server_base_url/Bar/ named Bar, you would use it like:
foo.Bar.get(42)
.then(function(bar_inst) {
console.log(bar_inst);
bar_inst.baz = 77;
bar_inst.save()
.then(function() {
console.log('bar_inst has been saved');
});
})
or
foo.BarList.get('filter_a=5&field_filter_b=abc,d')
.then(function(data) {
console.log(data.results);
})
Each instance in the data.result will be a foo.Bar instance.
You can add callbacks before sending to the server and after retrieving from the server using foo.Bar.pre_save(function (inst) {/*callback mutator*/}) and foo.Bar.post_restore( function(inst) { /*callback mutator*/}).
Anyways, this management task is not productized and it has only one user - me, but I have been using it for 2 years and it works great for me :-) We can work to get it working in your configuration if you like. Naturally the biggest caveat is the AngularJS 1.* dependency.

How to attach X509Certificate2 to webservice (Apple GSX / C# specific)

Apple released their New Generation WSDL on the 15 of August this year (2015) and the big change was that every call to the WSDL had to be validated with a certificate file.
I've done the process to get the certificate from Apple, and I've whitelisted our server IP, and I've even verified that I can get access to the service endpoint from our server by coding a simple interface using HttpWebRequest where I easily can attach the certificate using webRequest.ClientCertificates.Add(), so I know everything is ready for it to work.
But, my problem arises when I download the WSDL from https://gsxwsut.apple.com/apidocs/prod/html/WSArtifacts.html?user=asp
I import the WSDL into Visual Studio and when I try to make an instance of the client class, the only one I find is GsxWSEmeaAspPortClient, which seems to be correct as it has all the functions for authenticate and various tools, but it does not have ClientCertificates. It does have ClientCredentials which have ClientCertificate, but when I try to set the cert there, it's as tho it's never set.
I'm guessing the service code transmits the data via either HttpWebRequest or WebRequest, so if I just can get to the request code from my instance of the class (GsxWSEmeaAspPortClient) I can probably fix it, but I can't seem to get there.
I've looked at this question: How can I connect with Apple's GSX NewGeneration webservices with WCF? which suggests it really should be that easy, but I don't have the GsxWSEmeaAspService, only the GsxWSEmeaAspPortClient from my Visual Studio's generation of the WSDL.
If anyone has any ideas which can point me in any direction towards victory I'd be eternally grateful.
I'm using Visual Studio 2013 and the solution is .Net v4.5.1 if that makes any difference.
I've pasted new code here:
public void Authenticate() {
// Use custom binding with certificate authentication
BasicHttpBinding binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
// Create service endpoint
// Use proper endpoint address - eg. gsxapi.apple.com for production
EndpointAddress endpoint = new EndpointAddress("https://gsxapiit.apple.com/gsx-ws/services/emea/asp");
// Create new service
Apple.GsxWSEmeaAspPortClient service = new Apple.GsxWSEmeaAspPortClient(binding, endpoint);
// Set loaded certificate
service.ClientCredentials.ClientCertificate.Certificate = new X509Certificate2(
"[PathToContainerFromStep7].p12",
"[YourPasswordFromStep8]");
// Create authenticate request object
Apple.authenticateRequestType auth = new Apple.authenticateRequestType()
{
languageCode = "en",
userId = "[YourAppleServiceAccountNumber]",
userTimeZone = "[YourTimeZone]",
serviceAccountNo = "[YourSoldToNumber]"
};
// Authenticate to Apple GSX
Apple.authenticateResponseType session = service.Authenticate(auth);
// Assign your new session id object
userSessionId = new Apple.gsxUserSessionType() { userSessionId = session.userSessionId };
}

Login failed when a web service tries to communicate with SharePoint 2007

I created a very simple webservice in ASP.NET 2.0 to query a list in SharePoint 2007 like this:
namespace WebService1
{
/// <summary>
/// Summary description for Service1
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
// [System.Web.Script.Services.ScriptService]
public class Service1 : System.Web.Services.WebService
{
[WebMethod]
public string HelloWorld()
{
return "Hello World";
}
[WebMethod]
public string ShowSPMyList()
{
string username = this.User.Identity.Name;
return GetList();
}
private string GetList()
{
string resutl = "";
SPSite siteCollection = new SPSite("http://localhost:89");
using (SPWeb web = siteCollection.OpenWeb())
{
SPList mylist = web.Lists["MySPList"];
SPQuery query = new SPQuery();
query.Query = "<Where><Eq><FieldRef Name=\"AssignedTo\"/><Value Type=\"Text\">Ramprasad</Value></Eq></Where>";
SPListItemCollection items = mylist.GetItems(query);
foreach (SPListItem item in items)
{
resutl = resutl + SPEncode.HtmlEncode(item["Title"].ToString());
}
}
return resutl;
}
}
}
This web service runs well when tested using the built-in server of Visual Studio 2008. The username indicates exactly my domain account (domain\myusername).
However when I create a virtual folder to host and launch this web service (still located in the same machine with SP2007), I got the following error when invoking ShowSPMyList() method, at the line to execute OpenWeb(). These are the details of the error:
System.Data.SqlClient.SqlException: Cannot open database "WSS_Content_8887ac57951146a290ca134778ddc3f8" requested by the login. The login failed.
Login failed for user 'NT AUTHORITY\NETWORK SERVICE'.
Does anyone have any idea why this error happens? Why does the web service run fine inside Visual Studio 2008, but not when running stand-alone? I checked and in both cases, the username variable has the same value (domain\myusername).
Thank you very much.
Thank you very much for the replies. I'll look into the documents to see how i can change the settings related to the application pool as suggested.
I want to make clear that i wanted to build a webservice to run outside of sharepoint (but can be deployed on the same server with sharepoint).
Is there any way i can programmatically pass the credentials (another domain account instead of 'NT AUTHORITY\NETWORK SERVICE' by default) to sharepoint when invoking OpenWeb method? I believe if i'm able to do that then i can walkaround the security issue above.
When you create your own custom virtual folder and set it inside the IIS, it's highly possible that the user account who run the application pool of that particular IIS virtual directory is currently set to NT authority\Network Service.
You can check carefully, by looking closely of what is the actual application pool that run that particular IIS virtual directory.
From there, you can go to the "Application Pool" folder and right click, choose Properties. Select the "Identity" tab, and it will show you who is the user account that currently running the application pool.
Alternatively, you can refer to the SharePoint SDK, something similar to ExtractCrmAuthenticationToken in dynamics CRM to extract the Authentication Token ticket.
Or alternatively you can use Network Credential to embed your own custom user id and password.
Hope this helps,
hadi teo
I fully agree with Hadi, if this is something you want to just quickly test, for a proof of concept, you can change the credentials under what the Application pool runs, to a user that has permissions. Or you could use Identity Impersonate setting in your config file.
However resist the temptiation to do this in a production enviroment, use the proper authentication. It will come back, to bite you.
If you need to set this up for production, there is a couple of areas that you want to look at, duplicate SPN's, and deligation probably the most common areas that is not configured correctly. Your error however points to impersanation not happening.
Also make sure you are deploying the web service to its own web site that does not already run SharePoint. If you want the web service to run on the same web site as SharePoint read Creating a Custom Web Service.
You can check what application pool identity SharePoint is using by following the same instructions that Hadi writes, but for an app pool running SharePoint. Make sure to only change the application pool used by your web service and not SharePoint or else other permission errors could occur within SP. (There should be no reason but if you are interested in changing the app pool identity used by SharePoint follow these instructions.)
On solution would be to "impersonate" as the SharePoint System account using the following code:
SPSecurity.RunWithElevatedPrivileges(delegate()
{
// also dispose SPSite
using (SPSite siteCollection = new SPSite("http://localhost:89"))
{
using (SPWeb web = siteCollection.OpenWeb())
{
// ...
}
}
});