Magnolia Mail Module Doesn't Work - magnolia

Im trying to send an email using Mail Module in Magnolia CMS 4.5.4. The code I have so far is:
protected void sendEmail(CommentDTO comment){
if(comment!=null){
try{
MgnlMailFactory mailFactory = MailModule.getInstance().getFactory();
if(mailFactory!=null){
Map<String, Object> params = new HashMap<String, Object>();
MgnlEmail mail = mailFactory.getEmailFromTemplate("MyTemplate", params);
mail.setToList("whoever#whatever.co.uk");
mail.setBody("HELLO");
mail.setFrom("whoever#whatever.co.uk");
if(mail!=null){
MgnlMailHandler mmh = mailFactory.getEmailHandler();
if(mmh!=null){
mmh.prepareAndSendMail(mail);
}
}
}
}catch(Exception e){
}
}
}
The log I get is:
2013-02-22 16:52:30,357 INFO fo.magnolia.module.mail.handlers.SimpleMailHandler: Mail has been sent to: [2013-02-22 16:52:30,357 INFO fo.magnolia.module.mail.handlers.SimpleMailHandler: Mail has been sent to: [whoever#whatever.co.uk]
But the email never come...
Before this trace I get :
2013-02-22 16:52:24,212 WARN info.magnolia.cms.util.DeprecationUtil : A deprecated class or method was used: Use IoC!. Check the following trace: info.magnolia.module.mail.MailModule.getInstance(MailModule.java:80), info.magnolia.module.mail.MgnlMailFactory.getEmailHandler(MgnlMailFactory.java:69), the full stracktrace will be logged in debug mode in the info.magnolia.cms.util.DeprecationUtil category.
Eclipse marks the method MailModule.getInstance() as deprecated but I have no idea what I must to put instead.
Somebody can help me?
Thanks!

As there are no thrown Exceptions, I guess you wrongly configured your SMTP server or not at all. How to do this can be read here: http://documentation.magnolia-cms.com/modules/mail.html#ConfiguringSMTP
Also, assure that:
Your mail didn't land in any spam filter (maybe outside your mailbox)
There are no blocking firewalls (e.g. when running on localhost)

Ok, I finally solve it with this code:
protected void sendEmail(CommentDTO comment){
if(comment!=null){
try{
MgnlMailFactory mailFactory = MailModule.getInstance().getFactory();
if(mailFactory!=null){
Map<String, Object> params = new HashMap<String, Object>();
params.put("articleName", comment.getArticleName());
params.put("id", comment.getId() );
params.put("commentText", comment.getComment());
params.put("author", comment.getName());
MgnlEmail mail = mailFactory.getEmailFromTemplate("myTemplate", params);
mail.setBodyFromResourceFile();
if(mail!=null){
MgnlMailHandler mmh = mailFactory.getEmailHandler();
if(mmh!=null){
mmh.prepareAndSendMail(mail);
}
}
}
}catch(Exception e){
log.error("Error sending email: " +e.getMessage());
}
}
}
I think what it make it works was this line:
mail.setBodyFromResourceFile();
And, of course, a good configuration of the SMTP server.

Related

FCM throws 401 after some time for data message notification

I am sending data message notification from Java app server to the FCM rest endpoint. Everything works fine, data messages are received by the app without any issues, however after some time (without any noticeable trend) , FCM stars returning 401. I am using Apache common's HTTPClient library to make the http callss. This is the relevant code snippet
final HttpPost httpPost = new HttpPost("https://fcm.googleapis.com/v1/projects/proj1/messages:send");
httpPost.setHeader("Content-Type", "application/json");
httpPost.setHeader("Authorization", "Bearer "+ accessToken);
responseBody = httpclient.execute(httpPost, responseHandler);
And this snippet is for getting the access token for API authorization
static{
FileInputStream refreshToken = null;
refreshToken = new FileInputStream("C:/prj/proserviceaccoutkey.json");
googleCredentials=GoogleCredentials.fromStream(refreshToken).createScoped("https://www.googleapis.com/auth/firebase.messaging");
options = new FirebaseOptions.Builder() .setCredentials(googleCredentials).build();
}
// Gets called each time a data message needs to be sent
public static synchronized String getAccessToken()
{
if(googleCredentials.getAccessToken()==null)
try {
googleCredentials.refresh();
} catch (IOException e) {
e.printStackTrace();
}
return googleCredentials.getAccessToken().getTokenValue();
}
looks like googleCredentials.getAccessToken() will always return non-null, even when the cahce token in no longer valid, and this is why token was not getting refreshed in the code. Applied the following fix, and it's working now.
public static synchronized String getAccessToken()
{
if(googleCredentials!=null)
try {
googleCredentials.refresh();
} catch (IOException e) {
e.printStackTrace();
}
return googleCredentials.getAccessToken().getTokenValue();
}
Though, it's not really utilizing the cached token, as every time it will be refreshing the token, but my issue has been rsolved for now.

What is the right implementation of SPNEGO auth provider

I am writing a service that talks to Alfresco Core repository using Apache Chemistry opencmis library and need to authenticate through SPNEGO. Cmis library requires me to provide custom authentication provider which so far doesn't work for me. So far I came up with following:
public class KerberosAuthProvider extends AbstractAuthenticationProvider {
#Override
public Map<String, List<String>> getHTTPHeaders(String url) {
try {
String authToken = …. // generate token
Map<String, List<String>> headers = Maps.newHashMap();
headers.put("Authorization", Lists.newArrayList("Negotiate " + authToken));
return headers;
} catch (Exception ex) {
throw new IllegalStateException("Couldn't get token", ex);
}
}
}
I will appreciate any suggestions.
This is correct implementation. I was not generating token correctly so was denied access. I have used WireShark to confirm the Authorisation header was added to cmis request.

Best practice for deploying spring boot application on Amazon

I've devloped a chat bot application using the Facebook Messenger platform.
I used Spring Boot with embedded Tomcat for the web platform.
The application should run on Amazon aws, open to the WWW, and to be used as a webhook for recieving callbacks from Messenger over https.
I need an advice how to secure the application, so it won't be hacked or flooded with requests that are not coming from Facebook.
I thought to make the application require secured (ssl) connection, but using the "security.require_ssl=true" in application.properties didn't do the work. Perhaps I don't know what is the meaning of this and how to configure it propertly.
Is there a best practice how to block requests which are not https requests? Or a way to block requests which are coming outside Messenger in the application level?
Thank you very much!
EDIT
In the meantime, I blocked requests from other IPs in application layer using the handler interceptor:
#Configuration
public class MyWebApplicationInitializer implements WebApplicationInitializer, WebMvcConfigurer{
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new HandlerInterceptor() {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
if (! (request.getRemoteAddr().equals("173.252.88.66") || request.getRemoteAddr().equals("127.0.0.1")|| request.getRemoteAddr().equals("0:0:0:0:0:0:0:1"))){
logger.warn("Request is not coming from authorized remote address: " + request.getRemoteAddr()+". Rejecting");
response.getWriter().write("Unauthorized Address");
response.setStatus(401);
return false;
} else {
return true;
}
}
}
You should check the X-Hub-signature HTTP header available in the requests sent by Facebook to your webhook URL.
In your case, you may define a filter or interceptor for the verification of the signature. You can also do it in your controller as in the this example I found in RealTimeUpdateController.java from the spring social project.
private boolean verifySignature(String payload, String signature) throws Exception {
if (!signature.startsWith("sha1=")) {
return false;
}
String expected = signature.substring(5);
Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM);
SecretKeySpec signingKey = new SecretKeySpec(applicationSecret.getBytes(), HMAC_SHA1_ALGORITHM);
mac.init(signingKey);
byte[] rawHmac = mac.doFinal(payload.getBytes());
String actual = new String(Hex.encode(rawHmac));
return expected.equals(actual);
}
a lot to say so I am sure I will miss some points.
setting SSL is a first good thing but make sure you get a certificate. lets encrypt is a good thing if you dont want to pay for SSL certificate.
Just seeing aws provides an alternative to letsencrypt
Security Group You can see Security Group as something similar to a firewall so you can control which port is opened, external and internal flows.
Look at IAM which control who and how can get access to your AWS account
obvious : change your password. do not let default password for installation you could make on the instance
read some of https://aws.amazon.com/security/security-resources/ to get more information about what you can do
it won't be hacked or flooded with requests
sorry to say but most probably it will be - It does not need to be an advanced hacker to run scanner and scan IPs and check open ports / brute force login etc ...
Thanks to Guy Bouallet help I added the signature check.
I added it in my controller and not in the interceptor, to avoid the problem of How to read data twice in spring which seems a little complicated.
So here is it:
#RequestMapping(path = "/")
public void doHandleCallback(#RequestBody String body, #RequestHeader(value = "X-Hub-Signature") String signature) throws IOException {
if (!verifyRequestSignature(body.getBytes(), signature)){
logger.error ("Signature mismatch.");
throw new MismatchSignatureException(signature);
}
MessengerCallback callback = mapper.readValue(body, MessengerCallback.class);
logger.info("Incoming Callback: " + body );
for (EventData entry : callback.getEntry()) {
for (ReceivedMessagingObject message : entry.getMessaging()) {
if (message.isMessage() || message.isPostback()) {
doHandleMessage(message);
}
else if (message.isDelivery()){
doHandleDelivery(message);
}
}
}
}
private boolean verifyRequestSignature(byte[] payload, String signature) {
if (!signature.startsWith("sha1="))
return false;
String expected = signature.substring(5);
System.out.println("Expected signature: " + expected); //for debugging purposes
String hashResult = HmacUtils.hmacSha1Hex(APP_SECRET.getBytes(), payload);
System.out.println("Calculated signature: " + hashResult);
if (hashResult.equals(expected)) {
return true;
} else {
return false;
}
}
And this is the Exception handling class:
#ResponseStatus(value=HttpStatus.BAD_REQUEST, reason="Request Signature mismatch")
public class MismatchSignatureException extends RuntimeException {
private String signature;
public MismatchSignatureException(String signature) {
this.signature = signature;
}
#Override
public String getMessage() {
return "Signature mismatch: " + signature;
}

HttpGet not returning anything - android

I'm trying to setup an HTTP connection using the HttpGet but i'm not getting anything back from the website. The only text on the website is a string reading: "Error: Username not passed". I have looked at other questions/answers regarding this issue, but they go into parsing the JSON format. However, I'm just interested in viewing what i'm getting back in the response. Is this possible? Does the android code only accept a response in the JSON format? If so, doesn't this include a string similar to the one I should be getting back from the website? What am I missing? Here's the code I have:
public void onClick(View v) {
//Create a default HTTPClient to setup retrieve data functionality
httpclient = new DefaultHttpClient();
//Create new HTTP GET with URL to php file
httpget = new HttpGet("http://satpreet.com/mobile/auth.php");
try {
response = httpclient.execute(httpget);
entity = response.getEntity();
InputStream instream = entity.getContent();
resultdata = convertStreamToString(instream);
} catch (Exception e) {
Toast.makeText(getBaseContext(), "Hit Exception", Toast.LENGTH_LONG).show();
}
//For viewing the result
LinearLayout lView = new LinearLayout(this);
TextView myText = new TextView(this);
myText.setText(resultdata);
lView.addView(myText);
setContentView(lView);
The last part is probably not the best way to debug my code. Can you suggest a better way? I tried using the log.i however when I set up a filter to by Log Tag, nothing is caught.
Thank you.
Did you add the required permission
<uses-permission android:name="android.permission.INTERNET"/>
to the AndoridManifest?
Maybe also change this:
httpclient.execute(httpget);
to:
httpclient.execute(httpget, new BasicHttpContext());
Also notice that you have to use this code asynchronously. Otherwise you'll get some exceptions while running on a real device.

System.Net.Mail.SmtpFailedRecipientException: Mailbox name not allowed

I have written ASP.Net code to send mails from domain1.com mail account such as abc#domain1.com. This code work fine otherwise and the mails go. But when the same code executes on domain2.com, even with correct userid-pwd it gives the following error:
System.Net.Mail.SmtpFailedRecipientException: Mailbox name not allowed. The server response was: sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1) at System.Net.Mail.SmtpClient.Send(MailMessage message)
Is there any way to fix this?
If we have to add this domain in the list of allowed rcphosts, how can that be done?
The code written is something like this:
MailMessage message;
bool success;
message = new MailMessage(from, to);
Attachment file;
SmtpClient lclient;
lclient = new SmtpClient("mail.domain1.com", 587);
lclient.EnableSsl = false;
message.Body = body;
message.BodyEncoding = System.Text.Encoding.UTF8;
message.IsBodyHtml = true;
message.Subject = subject;
message.SubjectEncoding = System.Text.Encoding.UTF8;
lclient.SendCompleted += new
SendCompletedEventHandler(SendCompletedCallback);
lclient.UseDefaultCredentials = false;
lclient.Credentials = new NetworkCredential(userID, password);
try
{
lclient.Send(message);
success = true;
if (message != null)
message.Dispose();
success = true;
return (success);
}
catch (Exception ex)
{
//...
}
Thanks
The code works fine. The error is a rejection from the SMTP server. It would seem that the server, when accessed from Domain1, allows you to forward mail through it. When accessed from Domain2, it does not. Changing this would be a configuration on the SMTP server.
Note that this is common practice for SMTP services. They generally don't allow anybody to send mail through them to any address. (That would leave them wide open for spammers and other such unwanted activities.) So, if you're trying to access Domain1's SMTP service from outside of Domain1, it's probably just rejecting that.

Resources