I have to send an mail whenever an order is placed. I am using a spring boot application. I am using spring-boot-starter-mail. I am using gmail-smtp.
Problem: It takes 13 seconds to send a single email. It is a sooo costly operation.
Exception:
I want some performance optimization and and also I want to understand how e-commerce companies will send an email so quickly as soon as an order is placed.
public class SendEmailImpl implements SendEmail {
#Autowired
private JavaMailSender mailSender;
#Override
public String Sendmail(Sender sender) {
SimpleMailMessage smm = new SimpleMailMessage();
smm.setTo(sender.getDestinationEmail());
smm.setFrom(sender.getSourceEmail());
smm.setSubject(sender.getSubject());
smm.setText(sender.getDescription());
mailSender.send(smm);
return "The Message send successfully";
}
Config:
spring.mail.properties.mail.smtp.auth = true
spring.mail.properties.mail.smtp.connectiontimeout = 5000
spring.mail.properties.mail.smtp.timeout = 5000
spring.mail.properties.mail.smtp.writetimeout = 5000
spring.mail.properties.mail.smtp.starttls.enable = true
spring.mail.host = smtp.gmail.com
spring.mail.port = 587
spring.mail.username =
spring.mail.password =
Related
I send Email using Spring mail SMTP through Spring Batch. Sending each mail takes 1 second at least. And we would be sending 1000 mails per Batch job. Due the 1 second per mail , it seems it'll take lot of time to send all those 1000+ mails. So I planned to use multi-threading to send all emails in a chunk(size=100) of the job. And I succeeded a bit (only a bit) in sending mails with this approach.
The multi-threading works as long as the the total mail count is very small , like 40 email per Batch(Not even the size of the chunk). if the mail counts exceeds the count The SMTP throws java.net.sockettimeoutexception read timed out.
Even increasing the timeout is not working here. But when I send mails without multithreads, they work perfectly.
application.properties
spring.mail.properties.mail.smtp.auth=false
spring.mail.properties.mail.smtp.ehlo=false
spring.mail.properties.mail.smtp.ssl.enable=false
spring.mail.properties.mail.smtp.ssl.checkserveridentity=false
spring.mail.properties.mail.debug=false
spring.mail.properties[mail.smtp.connectiontimeout]=10000
spring.mail.properties[mail.smtp.timeout]=10000
spring.mail.properties[mail.smtp.writetimeout]=10000
spring.mail.properties[mail.mime.charset]=UTF-8
Writer
#Autowired
EmailSender emailSender;
ExecutorService executor = Executors.newCachedThreadPool();
Collection<Callable<Map<BBEmailOutreach, Boolean>>> tasks = new ArrayList<>();
items.stream().filter(item -> item != null).forEach(item -> {
tasks.add(new ParallelMail(item, emailSender));
}
try {
futureMailStatus = executor.invokeAll(tasks);
} catch (InterruptedException e) {
e.printStackTrace();
}
EmailSender.java
public class EmailSender {
#Autowired
private JavaMailSender javaMailSender;
public void sendEmail(EmailInfo emailInfo) {
MimeMessagePreparator preparator = new MimeMessagePreparator() {
public void prepare(MimeMessage mimeMessage) throws Exception {
MimeMessageHelper message = new MimeMessageHelper(mimeMessage,
true);
message.setTo(emailInfo.getToEmailAddress().split(","));
message.setFrom(new InternetAddress(emailInfo.getFromEmailAddress()));
message.setSubject(emailInfo.getSubject());
message.setText(emailInfo.getMessage(), true);
if(null != emailInfo.getCc() && emailInfo.getCc().length >1)
{
message.setCc(emailInfo.getCc());
}
if (emailInfo.getAttachmentPath() != null) {
FileSystemResource file = new FileSystemResource(
emailInfo.getAttachmentPath());
message.addAttachment(emailInfo.getAttachmentName(), file);
}
}
};
this.javaMailSender.send(preparator);
}
}
Exception
org.springframework.mail.MailSendException: Failed messages: javax.mail.MessagingException: Exception reading response;
nested exception is:
java.net.SocketTimeoutException: Read timed out
Please advise what can be done to use mutli-threading without any error.
IBM Notes 9
Vacation for 2 weeks
All incoming mail needs to be forwarded automatically to a colleague.
All incoming mail needs to also make it my inbox to be reviewed and followed up on when I return.
Here is what I found so far. Please explain steps if possible. I have no experience with Java and very limited experience with C over 5 years ago.
import lotus.domino.*;
import java.util.Vector;
public class JavaAgent extends AgentBase {
public void NotesMain() {
try {
Session session = getSession();
AgentContext agentContext = session.getAgentContext();
// (Your code goes here)
Database db = agentContext.getCurrentDatabase();
DocumentCollection dc =
agentContext.getUnprocessedDocuments();
Document reply;
Vector sendTo;
Document doc = dc.getFirstDocument();
while (doc != null) {
sendTo = doc.getAuthors();
if (!doc.isSentByAgent()) {
reply = doc.createReplyMessage(false);
reply.replaceItemValue
("Subject", "Re: " +
doc.getItemValueString("Subject"));
reply.replaceItemValue(
"Body", "On vacation until 8/15\n");
reply.send(sendTo);
}
doc = dc.getNextDocument(doc);
}
} catch(Exception e) {
e.printStackTrace();
}
}
}
The last time I was gone the admin set up forwarding but it skipped my inbox entirely. It got redirected to my colleague before hitting my inbox. I am not sure how he did this. I have found the code for setting up an autoreply to sender with a canned message about being on vacation. I want to edit this code to instead send the subject and body of the message to another recipient.
I expect to have incoming messages arrive in my inbox, my colleague's inbox, and he can reply to the original sender as well.
simply set up a mail rule (Tools - Rules). You can turn it off upon your return.
I have a project where we are using ArdanStudios smppclient to connect to an SMPPServer. We can send messages to the SMPP Server and they get delivered to the handset. When the hand set replies or sends to the shortcode we do get a received message event but the message text is blank.
We are using CloudHopper internally to simulate the SMPP Server, I want to confirm that there isn't a problem on our end when receiving messages but I can not figure out a way to simulate an MO (mobile originated) message sent from Cloudhopper server to our connected ArdanClient. Any ideas ?
You have two questions in one Pal. I suggest you break it up. For the first one basically you have to override the firePduRequestReceived methos of class DefaultSmppSessionHandler:
#Override
public PduResponse firePduRequestReceived(PduRequest pduRequest) {
PduResponse response = pduRequest.createResponse();
if (pduRequest.getCommandId() == SmppConstants.CMD_ID_DELIVER_SM) {
processMO(pduRequest);
}
return response;
}
private void processsMO(PduRequest request){
DeliverSm mo = (DeliverSm) request;
int length = mo.getShortMessageLength();
Address sourceAddr = mo.getSourceAddress();
Address destAddr = mo.getDestAddress();
byte[] shortMessage = mo.getShortMessage();
String sms= new String(shortMessage);
//Do Something....
}
I am trying to use Play Framework to send out email. In applications.conf, when I set smtp.mock=true , it works perfectly well:
[info] application - HTML: Welcome to Play20StartApp. <br> Click on this link : http://localhost:9000/confirm/d77ea256-0d2e-4df5-b66e-e034159f8042 to confirm your email.<br><br>--<br>null
[debug] application - Mail sent - SMTP:smtp.google.com:465 SSL:yes user:username#gmail.com password:password
However, when I comment smtp.mock=true and attempt to send real emails, I get this error:
[debug] application - Mail.sendMail: Mail will be sent to user1#gmail.com
[ERROR] [09/26/2013 03:46:05.014] [application-akka.actor.default-dispatcher-2] [TaskInvocation] From address required
org.apache.commons.mail.EmailException: From address required
I have set smtp.user to a proper value, i.e. server#businessdomain.com . Any idea what causes this error?
Troubleshooting steps
The emails used are real emails, for the purpose of posting, they are anonymized. Likewise, a real domain name is used
Tested with a working local mail server (exim), as well as directly sending through Gmail (smtp.google.com) and Google Apps (aspmx.l.google.com) servers. These settings have been verified using mail clients.
The Java code snippet below works perfectly,
import java.util.;
import javax.mail.;
import javax.mail.internet.;
import javax.activation.;
public class SendEmail
{
public static void main(String [] args)
{
String to = "recipient#mydomain.com";
String from = "sender#mydomain.com";
String host = "localhost";
Properties properties = System.getProperties();
// Setup mail server
properties.setProperty("mail.smtp.host", host);
// Get the default Session object.
Session session = Session.getDefaultInstance(properties);
try{
MimeMessage message = new MimeMessage(session);
// Set From: header field of the header.
message.setFrom(new InternetAddress(from));
message.addRecipient(Message.RecipientType.TO,
new InternetAddress(to));
message.setSubject("Subject of email");
message.setText("This is actual message");
Transport.send(message);
System.out.println("Sent message successfully....");
}catch (MessagingException mex) {
mex.printStackTrace();
}
}
}
In the event that you are wrapping your mailer action in a Future (or Play Java equivalent), then it may be a variable scoping issue that you're hitting:
This works:
val mail = use[MailerPlugin].email
val async: Future[Unit] = Future{
mail.setSubject(subject)
mail.setRecipient(recipient)
mail.setFrom(from)
mail.send(body)
}
async.onFailure{case(e)=>
Logger.error(s"mailer failed for $recipient due to: ${e.getMessage}")
}
This does not work:
val mail = use[MailerPlugin].email
mail.setSubject(subject)
mail.setRecipient(recipient)
mail.setFrom(from)
val async: Future[Unit] = Future{mail.send(body)}
async.onFailure{case(e)=>
Logger.error(s"mailer failed for $recipient due to: ${e.getMessage}")
}
I assumed that the enclosing scope would be available within the Future closure; in this case definitely not since underlying Apache Commons mailer bails with "From address required". Sure enough, setting smtp.mock=true reveals that fromAddress is null when mail.setFrom and friends are populated outside of Future{...} scope.
Interestingly, even if I break out async val into a local method and pass in constructed mailer and body text:
private def async(mail: MailerAPI, body: String): Future[Unit] = Future{
mail.send(body)
}
the mail properties set outside of the Future still wind up null despite passing a constructed mailer directly -- surprising, no?
I'm currently using Topic based communication using JADE. I'm able to register a JADE agent using jade.core.messaging.TopicManagementFEService thereby connecting to the main-container in the same platform.
The details are below:
Main-Container: a simple LAMP/WAMP Server that hosts the Main-Container.
Client: An Android Emulator(testing purpose) to connect to the main-container.
Currently,
Server starts the main-container
Android emulator connects to the Main-container successfully (Agent created along with Topic Mgmt Service enabled)
Server is sending messages based on a specific topic.
But my Android Client is not able to receive this message although the topic registered is the same on both ends!
You can see the code below:
Server Side:
TopicManagementHelper topicHelper = (TopicManagementHelper) getHelper(TopicManagementHelper.SERVICE_NAME);
final AID sensorTopic = topicHelper.createTopic("JADE");
topicHelper.register(sensorTopic);
addBehaviour(new TickerBehaviour(this, TIMER_VALUE_IN_MILLISECONDS) {
private static final long serialVersionUID = -2567778187494378326L;
public void onTick() {
ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
msg.addReceiver(eventTopic);
msg.setContent(eventValue);
myAgent.send(msg);
}
});
Android Side:
// Registering on Android Side as well
TopicManagementHelper topicHelper = (TopicManagementHelper) getHelper(TopicManagementHelper.SERVICE_NAME);
topic = topicHelper.createTopic("JADE"); // See, same topic!
topicHelper.register(topic);
behaviour = new myBehaviour(this, TIMER_VALUE_IN_MILLISECONDS, topic);
addBehaviour(behaviour);
private class myBehaviour extends TickerBehaviour {
private static final long serialVersionUID = 4782913834042415090L;
AID topic;
Agent agent;
MessageTemplate tpl;
public myBehaviour(Agent a, long period, AID topic) {
super(a, period);
this.agent = a;
this.topic = topic;
}
public void onTick() {
tpl = MessageTemplate.MatchTopic(topic);
ACLMessage msg = receive(tpl);
if (msg != null) {
logger.log(Level.INFO, "Agent "+ agent.getLocalName() +
": Message about topic "+ topic.getLocalName() +" received. \n" +
"Content is " + msg.getContent());
data = msg.getContent();
} else {
logger.log(Level.INFO, "In here..."); // Always executes only this code!
block();
}
}
}
Where am I going wrong here? It always executes the else part in the Android side which is obvious to say that message received is NULL!
Never mind. The logic was wrong. The Android-Agent was not identifying itself to the Central-Agent.
I set the Ontology so that the Central Agent is able to identify such message and sends the message accordingly. Now, it is receiving messages!
Self-help works sometimes! ;-)
Receiving topic messages doesn't work correctly with Android up to version 4.3.0 in JADE. Android can send out topic messages but can't receive them. I found this out through my own issues. I've posted more info about it in my own question on stack overflow.
Take a look. JADE Leap Android App unable to receive topic messages