Schedule tasks using Quartz and Spring boot - spring-boot

I would Like to send emails daily using Spring boot, the user specifies the time of sending, I used quartz to schedule my Job.
The recipients of emails have(id, emailAddress, deadline) The email will be sent to the people who have deadline = Today + X.. (The user specifies the X).
For example: The user specifies that X is number 1, so we're interested in people who have deadline tomorow.
Day1: the app sent emails to people who have deadline = today +1..
Day2: I want that the application send the email at Day2 to new recipients, but with the code below, the email is sent to the ones who received it in Day1, and that's not what I need.
#PostMapping("/scheduleEmailPeriodic")
public ResponseEntity<ScheduleEmailResponse> SendScheduleEmailPeriodic(
#Valid #RequestBody PeriodicNotification scheduleEmailRequest) throws Exception {
ens.schedulePeriodicNotification(scheduleEmailRequest);
LocalDate localDateTime = LocalDate.now();
LocalTime localTime = LocalTime.parse(scheduleEmailRequest.getSendingTime());
try {
ZonedDateTime dateTime = ZonedDateTime.of(localDateTime, localTime,ZoneId.of("Africa/Casablanca"));
if (dateTime.isBefore(ZonedDateTime.now())) {
ScheduleEmailResponse scheduleEmailResponse = new ScheduleEmailResponse(false,
"dateTime must be after current time");
return ResponseEntity.badRequest().body(scheduleEmailResponse);
}
JobDetail jobDetail = buildPeriodicJobDetail(scheduleEmailRequest);
Trigger trigger = buildJobTriggerPeriodic(jobDetail, dateTime);
scheduler.scheduleJob(jobDetail, trigger);
ScheduleEmailResponse scheduleEmailResponse = new ScheduleEmailResponse(true, jobDetail.getKey().getName(),
jobDetail.getKey().getGroup(), "Email Scheduled Successfully!");
return ResponseEntity.ok(scheduleEmailResponse);
} catch (SchedulerException ex) {
logger.error("Error scheduling email", ex);
ScheduleEmailResponse scheduleEmailResponse = new ScheduleEmailResponse(false,
"Error scheduling email. Please try later!");
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(scheduleEmailResponse);
}
}
private JobDetail buildPeriodicJobDetail(PeriodicNotification scheduleEmailRequest) {
JobDataMap jobDataMap = new JobDataMap();
List<String> recipients = fileRepo.findWantedEmails(scheduleEmailRequest.getDaysNum());
if(recipients.isEmpty()) {
throw new RuntimeException("Aucun destinataire trouvé");
}
String[] to = recipients.stream().toArray(String[]::new);
jobDataMap.put("recipients", to);
jobDataMap.put("subject", scheduleEmailRequest.getSubject());
jobDataMap.put("body", scheduleEmailRequest.getMessage());
return JobBuilder.newJob(EmailJob.class).withIdentity(UUID.randomUUID().toString(), "email-jobs")
.withDescription("Send Email Job").usingJobData(jobDataMap).storeDurably().build();
}
private Trigger buildJobTriggerPeriodic(JobDetail jobDetail, ZonedDateTime startAt) {
return TriggerBuilder.newTrigger().forJob(jobDetail)
.withIdentity(jobDetail.getKey().getName(), "email-triggers")
.withDescription("Send Periodic Email Trigger")
.withSchedule(SimpleScheduleBuilder
.repeatHourlyForever(24))
.startAt(Date.from(startAt.toInstant()))
.build();
}
This is the email job:
#Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
logger.info("Executing Job with key {}", context.getJobDetail().getKey());
JobDataMap jobDataMap = context.getMergedJobDataMap();
String subject = jobDataMap.getString("subject");
String body = jobDataMap.getString("body");
String[] recipients = (String[])jobDataMap.get("recipients");
sendMail("smsender4#gmail.com", recipients, subject, body);
}
private void sendMail(String fromEmail, String[] toEmail, String subject, String body) {
try {
logger.info("Sending Email to {}", Arrays.toString(toEmail));
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper messageHelper = new MimeMessageHelper(message, StandardCharsets.UTF_8.toString());
messageHelper.setSubject(subject);
messageHelper.setText(body, true);
messageHelper.setFrom(fromEmail);
messageHelper.setTo(toEmail);
mailSender.send(message);
} catch (MessagingException ex) {
logger.error("Failed to send email to {}", Arrays.toString(toEmail));
}
}
}
I really need Help, I need to get new recipients everyday, not to send the email to the same recipients.

You're sending emails based on date - but you don't track when emails were sent for a particular user. So if you will send one email to user1 Today - then user1 will still be in the condition for the next day. You need to add a flag (or some other logic ) saying that email was already sent for this user

Related

Schedule emails using Spring boot and Quartz

I would Like to send emails daily using Spring boot, the user specifies the time of sending, I used quartz to schedule my Job. The recipients of emails have(id, emailAddress, deadline) The email will be sent to the people who have deadline = Today + X.. (The user specifies the X). For example: The user specifies that X is number 1, so we're interested in people who have deadline tomorow.
Day1: the app sent emails to people who have deadline = today +1..
Day2: I want that the application send the email at Day2 to new recipients, but with the code below, the email is sent to the same recipients of Day1, and that's not what I need.
#PostMapping("/**")
public ResponseEntity<ScheduleEmailResponse> SendScheduleEmailPeriodic(
#Valid #RequestBody PeriodicNotification scheduleEmailRequest) throws Exception {
ens.schedulePeriodicNotification(scheduleEmailRequest);
LocalDate localDateTime = LocalDate.now();
LocalTime localTime = LocalTime.parse(scheduleEmailRequest.getSendingTime());
try {
ZonedDateTime dateTime = ZonedDateTime.of(localDateTime, localTime,ZoneId.of("**"));
if (dateTime.isBefore(ZonedDateTime.now())) {
ScheduleEmailResponse scheduleEmailResponse = new ScheduleEmailResponse(false,
"dateTime must be after current time");
return ResponseEntity.badRequest().body(scheduleEmailResponse);
}
JobDetail jobDetail = buildPeriodicJobDetail(scheduleEmailRequest);
Trigger trigger = buildJobTriggerPeriodic(jobDetail, dateTime);
scheduler.scheduleJob(jobDetail, trigger);
ScheduleEmailResponse scheduleEmailResponse = new ScheduleEmailResponse(true, jobDetail.getKey().getName(),
jobDetail.getKey().getGroup(), "Email Scheduled Successfully!");
return ResponseEntity.ok(scheduleEmailResponse);
} catch (SchedulerException ex) {
logger.error("Error scheduling email", ex);
ScheduleEmailResponse scheduleEmailResponse = new ScheduleEmailResponse(false,
"Error scheduling email. Please try later!");
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(scheduleEmailResponse);
}
}
private JobDetail buildPeriodicJobDetail(PeriodicNotification scheduleEmailRequest) {
JobDataMap jobDataMap = new JobDataMap();
List<String> recipients = fileRepo.findWantedEmails(scheduleEmailRequest.getDaysNum());
if(recipients.isEmpty()) {
throw new RuntimeException("Aucun destinataire trouvé");
}
String[] to = recipients.stream().toArray(String[]::new);
jobDataMap.put("recipients", to);
jobDataMap.put("subject", scheduleEmailRequest.getSubject());
jobDataMap.put("body", scheduleEmailRequest.getMessage());
return JobBuilder.newJob(EmailJob.class).withIdentity(UUID.randomUUID().toString(), "email-jobs")
.withDescription("Send Email Job").usingJobData(jobDataMap).storeDurably().build();
}
private Trigger buildJobTriggerPeriodic(JobDetail jobDetail, ZonedDateTime startAt) {
return TriggerBuilder.newTrigger().forJob(jobDetail)
.withIdentity(jobDetail.getKey().getName(), "email-triggers")
.withDescription("Send Periodic Email Trigger")
.withSchedule(SimpleScheduleBuilder
.repeatHourlyForever(24))
.startAt(Date.from(startAt.toInstant()))
.build();
}
This is the job:
#Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
logger.info("Executing Job with key {}", context.getJobDetail().getKey());
JobDataMap jobDataMap = context.getMergedJobDataMap();
String subject = jobDataMap.getString("subject");
String body = jobDataMap.getString("body");
String[] recipients = (String[])jobDataMap.get("recipients");
sendMail("**", recipients, subject, body);
}
private void sendMail(String fromEmail, String[] toEmail, String subject, String body) {
try {
logger.info("Sending Email to {}", Arrays.toString(toEmail));
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper messageHelper = new MimeMessageHelper(message, StandardCharsets.UTF_8.toString());
messageHelper.setSubject(subject);
messageHelper.setText(body, true);
messageHelper.setFrom(fromEmail);
messageHelper.setTo(toEmail);
mailSender.send(message);
} catch (MessagingException ex) {
logger.error("Failed to send email to {}", Arrays.toString(toEmail));
}
}
}

Send emails to multiple email addresses, It feeds email addresses from a csv file

I wanna create an application to send emails to several recipients. It feeds email addresses from a csv file and sends an email to each recipient, and I'm getting some trouble doing this.
Could you help me please?
Here is my CSVHelper.java
#Component
public class CSVHelper
{
public static String TYPE = "text/csv";
static String[] HEADERs = { "id", "email", "dateEcheance"};
//This method is used to filter the csv file and get only the emails
public List<ContactsFile> csvToEmails() throws NumberFormatException, ParseException
{
InputStream is = null;
try (BufferedReader fileReader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
CSVParser csvParser = new CSVParser(fileReader, CSVFormat.DEFAULT.withFirstRecordAsHeader().withIgnoreHeaderCase().withTrim());)
{
List<ContactsFile> emailsList = new ArrayList<>();
Iterable<CSVRecord> csvRecords = csvParser.getRecords();
for (CSVRecord csvRecord : csvRecords)
{
ContactsFile contact = new ContactsFile(csvRecord.get("email"));
emailsList.add(contact);
}
System.out.println(emailsList);
return emailsList;
}
catch (IOException e) { throw new RuntimeException("fail to get emails: " + e.getMessage()); }
}
We call csvToEmails() method in the controller to send the emails
#Autowired
private CSVHelper csvHelper;
#PostMapping("/getdetails")
public #ResponseBody EmailNotification sendMail(#RequestBody EmailNotification details) throws Exception {
MimeMessage message = sender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message,
MimeMessageHelper.MULTIPART_MODE_MIXED_RELATED,
StandardCharsets.UTF_8.name());
try {
helper.setTo((InternetAddress) csvHelper.csvToEmails());
helper.setText(details.getMessage(),true);
helper.setSubject("Test Mail");
} catch (javax.mail.MessagingException e) {
e.printStackTrace();
}
sender.send(message);
return details;
this is an example of the csv file:
id,email,dateEcheance
1,address#email.com,10/05/2021
2,address2#email.com,10/02/2021
I'm new to spring boot, and I'm in trouble completing this project.
Assuming that you've mail server configurations in place. First, you need to provide the JavaMailSender implementation. Spring does provide the implementation for the same. You've to create a bean and config the mail server configurations as follows.
#Configuration
public class MailConfig {
#Autowired
private Environment env;
#Bean
public JavaMailSender mailSender() {
try {
JavaMailSenderImpl mailSenderImpl = new JavaMailSenderImpl();
mailSenderImpl.setHost(env.getRequiredProperty("mail.smtp.host"));
mailSenderImpl.setUsername(env.getRequiredProperty("mail.smtp.username"));
mailSenderImpl.setPassword(env.getRequiredProperty("mail.smtp.password"));
mailSenderImpl.setDefaultEncoding(env.getRequiredProperty("mail.smtp.encoding"));
mailSenderImpl.setPort(Integer.parseInt(env.getRequiredProperty("mail.smtp.port")));
mailSenderImpl.setProtocol(env.getRequiredProperty("mail.transport.protocol"));
Properties p = new Properties();
p.setProperty("mail.smtp.starttls.enable", "true");
p.setProperty("mail.smtp.auth", "true");
mailSenderImpl.setJavaMailProperties(p);
return mailSenderImpl;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
Configuration settings in application.properties. Add settings according to the mail server.
# SMTP mail settings
mail.smtp.host=**********
mail.smtp.username=**********
mail.smtp.password=**********
mail.smtp.port=**********
mail.smtp.socketFactory.port=**********
mail.smtp.encoding=utf-8
mail.transport.protocol=smtp
mail.smtp.auth=true
mail.smtp.timeout=10000
mail.smtp.starttls.enable=true
mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory
CSVHelper.java
#Component
public class CSVHelper {
// This method is used to filter the csv file and get only the emails
public List<String> csvToEmails() {
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("csvFile.csv");
try (BufferedReader fileReader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
CSVParser csvParser = new CSVParser(fileReader,
CSVFormat.DEFAULT.withFirstRecordAsHeader().withIgnoreHeaderCase().withTrim());) {
List<String> emails = new ArrayList<>();
Iterable<CSVRecord> csvRecords = csvParser.getRecords();
for (CSVRecord csvRecord : csvRecords) {
String email = csvRecord.get("email");
emails.add(email);
}
return emails;
} catch (IOException e) {
throw new RuntimeException("fail to get emails: " + e.getMessage());
}
}
}
Send mail service
#Service
public class MailSenderService {
#Autowired
private CSVHelper csvHelper;
#Autowired
private JavaMailSender sender;
public void sendMail(EmailNotification details) {
try {
List<String> recipients = csvHelper.csvToEmails();
String[] to = recipients.stream().toArray(String[]::new);
JavaMailSenderImpl jms = (JavaMailSenderImpl) sender;
MimeMessage message = jms.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
// add the sender email address below
helper.setFrom("sender#mail.com");
helper.setTo(to);
helper.setText(details.getMessage(), true);
helper.setSubject("Test Mail");
sender.send(message);
} catch (javax.mail.MessagingException | NumberFormatException e) {
// action for exception case
}
}
}

how to format tables in Mails / outlook

I am sending email using Spring MVC but It is showing differently In Browser and outlook email
#Service("emailService")
public class EmailService {
#Autowired
private JavaMailSender mailSender;
StringBuilder ResponseTable=new StringBuilder();
public void sendMail(String emailid,String subject,int
tracking_id,String classification_type){
MimeMessage message=mailSender.createMimeMessage();
MimeMessageHelper helper=new MimeMessageHelper(message,true,"UTF- 8");
helper.setTo(emailid);
helper.setText(ResponseTable.toString(),true);
helper.setSubject(subject);
mailSender.send(message);
}
}
You can use a velocity Engine Template to create a custom template :
create your template mailTemplate.vm
create a methode where you can insert you data in a model
create a methode to insert this model in your template
1.mailTemplate.vm
<html>
<head></head>
<body>
<p>hello,</p>
<p>${variable}</p>
</body>
</html>
Create Model to send the Notification Mail
public Boolean NotificationMail(String sender, String receiver, String url,
String subject,String footer) {
LOG.info(" ... Sending new Subscription Notification Mail ");
try {
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
mailSender.setHost(mailHost);
mailSender.setPort(port);
mailSender.setJavaMailProperties(setMailProperties());
Map<String, Object> model = new HashMap<String, Object>();
model.put("variable", "hello this is the text will be display in the mail");
String body = getVelocityTemplate(model);
LOG.info("Mail host {} , Port {} , url {} , sender {} , receiver {} , subject {} , body {} ",
mailHost, port, url, sender, receiver, subject, body);
Boolean sent = mailService.sendMailWithImg(sender, receiver, subject, body);
return true;
} catch (IllegalArgumentException e) {
LOG.error("IllegalArgumentException , Missing configuration", e);
} catch (Exception e) {
LOG.error("General Exception :{}", e);
}
return false;
}
insert model in the Template
protected String getVelocityTemplateContent(Map<String, Object> model) {
StringWriter stringWriter = new StringWriter();
StringBuilder builder = new StringBuilder();
builder.append("/template/mailTemplate.vm");
try {
VelocityEngineUtils.mergeTemplate(velocityEngine, builder.toString(), "UTF8", model,
stringWriter);
return stringWriter.toString();
} catch (Exception e) {
LOG.error("Error",e);
}
return null;
}
}

unable to make activemq consumer to deque

I am creating a JMS chat application using activemq and spring boot. I am trying to send message from producer to multiple subscribers. I am able to send message i.e message is en-queued. but in my receiver part message is unable to de-queue.` I am using the below code for communicating message from producer to multiple subscribers.
public class WelcomeController implements MessageListener {
public static Boolean TRANSACTIONAL = false;
public static String TOPIC_NAME = "firstTopic";
public static String BROKER_URL = "tcp://localhost:61616";
public static String BROKER_USERNAME = "admin";
public static String BROKER_PASSWORD = "admin";
public void createProducer() throws JMSException {
Connection connection = null;
Session session = null;
try {
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory();
connectionFactory.setBrokerURL(BROKER_URL);
connectionFactory.setPassword(BROKER_USERNAME);
connectionFactory.setUserName(BROKER_PASSWORD);
connection = connectionFactory.createConnection();
connection.setClientID("CircliTopic");
connection.start();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
for (int i = 1; i <= 3; i++) {
session = connection.createSession(TRANSACTIONAL,
Session.AUTO_ACKNOWLEDGE);
Topic destination = session.createTopic(TOPIC_NAME);
MessageProducer producer = session.createProducer(destination);
TextMessage message = session.createTextMessage();
message.setText( "My text message was send and received");//
System.out.println("Sending text '" + message + "'");
producer.send(message);
MessageConsumer consumer = session
.createDurableSubscriber(destination, "Listener" + i);
consumer.setMessageListener(new WelcomeController());
}
} finally {
connection.close();
}`
}
#Override
public void onMessage(Message message) {
try {
if (message instanceof TextMessage) {
TextMessage text = (TextMessage) message;
System.out.println(" - Consuming text msg: " + text.getText());
} else if (message instanceof ObjectMessage) {
ObjectMessage objmsg = (ObjectMessage) message;
Object obj = objmsg.getObject();
System.out.println(" - Consuming object msg: " + obj);
} else {
System.out.println(
" - Unrecognized Message type " + message.getClass());
}
} catch (JMSException e) {
e.printStackTrace();
}
}
I am able to get consuming text message in my console but my message is not de-queued to the subscribers and also in my activemq server message is not dequeued.
You are creating a Topic subscription only after the message has been sent and that won't work because these are Topics and a Topic with no subscriptions simply discards all messages sent to it. You need to establish a durable Topic subscription prior to any messages being sent, or switch to Queues if your design allows as a Queue will store a message sent to it until consumed.
It is hard to say more without knowing your requirements but it seems you need to spend a little bit more time understanding how Topics work.

Java send email through gmail, sometimes works sometimes hang

I am sending email by Gmail through my web app.
However, sometimes it is working fine but sometimes it just stop without any message.
Does anyone know how to solve this?
In my spring AppConfig.java
#Bean
public JavaMailSender getMailSender(){
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
mailSender.setHost("smtp.gmail.com");
mailSender.setPort(587);
mailSender.setUsername("my email from");
mailSender.setPassword("my email password");
Properties javaMailProperties = new Properties();
javaMailProperties.put("mail.smtp.starttls.enable", "true");
javaMailProperties.put("mail.smtp.auth", "true");
//javaMailProperties.put("mail.transport.protocol", "smtps");
javaMailProperties.put("mail.transport.protocol", "smtp");
javaMailProperties.put("mail.debug", "true");
mailSender.setJavaMailProperties(javaMailProperties);
return mailSender;
}
In my mailService.java
public void sendEmailWithTemplate(Activity activity, Object object) {
Member member = (Member) object;
MimeMessagePreparator verificationEmail = getEmailFromActivity(activity, member);
try {
mailSender.send(verificationEmail);
System.out.println("Message sent.............................");
} catch (MailException ex) {
System.err.println(ex.getMessage());
}
}
private MimeMessagePreparator getEmailFromActivity(final Activity activity, final Member member) {
MimeMessagePreparator preparator = new MimeMessagePreparator() {
public void prepare(MimeMessage mimeMessage) throws Exception {
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
helper.setSubject(activity.getActivity_subject());
helper.setFrom("my from email");
helper.setTo(member.getEmail());
String mailContent = activity.getActivity_content();
helper.setText(mailContent, true);
}
};
return preparator;
}
Sometimes its working fine and I will be able to send the mail, but sometime is just stop for more than 20 minutes at:
DEBUG SMTP: enable SASL
DEBUG SMTP: useEhlo true, useAuth false
DEBUG SMTP: trying to connect to host "smtp.gmail.com", port 587, isSSL false
This is the method I get from other post, but I can't look back the post.
Activity is one of my object storing the subject and content.
public void sendEmailWithActivity(Activity activity, Object object, String path) {
try {
Member member = (Member) object;
String host = "smtp.gmail.com";
String username = "email";
String password = "password";
String body = activity.getActivity_content();
String name = activity.getActivity_name();
String subject = activity.getActivity_subject();=
//Set the properties
Properties props = new Properties();
props.put("mail.smtps.auth", "true");
// Set the session here
Session session = Session.getDefaultInstance(props);
MimeMessage msg = new MimeMessage(session);
// set the message content here
msg.setSubject(subject);
msg.setContent(body, "text/html");
msg.setFrom(new InternetAddress(username));
msg.addRecipient(Message.RecipientType.TO,
new InternetAddress(member.getEmail()));
Transport t = session.getTransport("smtps");
t.connect(host, username, password);
t.sendMessage(msg, msg.getAllRecipients());
t.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}

Resources