/* * $Id$ * * Copyright 2014 University of Dundee. All rights reserved. * Use is subject to license terms supplied in LICENSE.txt */ package omero.cmd.mail; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.mail.MailException; import ome.api.IQuery; import ome.api.local.LocalAdmin; import ome.parameters.Parameters; import ome.services.mail.MailUtil; import ome.system.EventContext; import omero.cmd.HandleI.Cancel; import omero.cmd.ERR; import omero.cmd.Helper; import omero.cmd.IRequest; import omero.cmd.Response; import omero.cmd.SendEmailRequest; import omero.cmd.SendEmailResponse; import ome.model.meta.Experimenter; /** * Callback interface allowing to send email using JavaMailSender, supporting * MIME messages through preparation callbacks. * * @author Aleksandra Tarkowska, A (dot) Tarkowska at dundee.ac.uk * @since 5.1.0 */ public class SendEmailRequestI extends SendEmailRequest implements IRequest { private final static Logger log = LoggerFactory .getLogger(SendEmailRequestI.class); private static final long serialVersionUID = -1L; private final SendEmailResponse rsp = new SendEmailResponse(); private String sender = null; private List<String> recipients = new ArrayList<String>(); private final MailUtil mailUtil; private Helper helper; public SendEmailRequestI(MailUtil mailUtil) { this.mailUtil = mailUtil; } // // CMD API // public Map<String, String> getCallContext() { Map<String, String> all = new HashMap<String, String>(); all.put("omero.group", "-1"); return all; } public void init(Helper helper) { this.helper = helper; final EventContext ec = ((LocalAdmin) helper.getServiceFactory() .getAdminService()).getEventContextQuiet(); if (!ec.isCurrentUserAdmin()) { throw helper.cancel(new ERR(), null, "no-permissions", "ApiUsageException", String.format("You have no permissions to send email.")); } rsp.invalidusers = new ArrayList<Long>(); rsp.invalidemails = new ArrayList<String>(); if (!everyone && groupIds.isEmpty() && userIds.isEmpty()) throw helper.cancel(new ERR(), null, "no-body", "ApiUsageException", String.format("No recipients specified.")); this.sender = mailUtil.getSender(); if (StringUtils.isBlank(this.sender)) throw helper.cancel(new ERR(), null, "no-sender", "ApiUsageException", String.format("omero.mail.from cannot be empty.")); if (StringUtils.isBlank(subject)) throw helper.cancel(new ERR(), null, "no-subject", "ApiUsageException", String.format("Email must contain subject.")); if (StringUtils.isBlank(body)) throw helper.cancel(new ERR(), null, "no-body", "ApiUsageException", String.format("Email must contain body.")); this.recipients = parseRecipients(); this.recipients.addAll(parseExtraRecipients()); rsp.total = this.recipients.size(); rsp.success = 0; if (this.recipients.isEmpty()) this.helper.setSteps(1); else this.helper.setSteps(this.recipients.size()); } public Object step(int step) throws Cancel { helper.assertStep(step); // early exist try { this.recipients.get(step); } catch (IndexOutOfBoundsException e) { return null; } String email = this.recipients.get(step); try { mailUtil.sendEmail(this.sender, email, subject, body, html, null, null); } catch (MailException me) { log.error(me.getMessage()); rsp.invalidemails.add(email); } rsp.success+=1; return null; } @Override public void finish() throws Cancel { // no-op } public void buildResponse(int step, Object object) { helper.assertResponse(step); if (helper.isLast(step)) { helper.setResponseIfNull(rsp); } } public Response getResponse() { return helper.getResponse(); } private List<String> parseRecipients() { /* * Depends on which parameters are set variants of the following query * should be executed: * * select distinct e from Experimenter as e join fetch * e.groupExperimenterMap as map join fetch map.parent g where 1=1 // * hack to avoid plenty of if statement in conditions below and g.id = * :active // active users by default, all = false and e.id in // * groupIds (select m.child from GroupExperimenterMap m where * m.parent.id in (:gids) ) or e.id in (:eids) // userIds */ Parameters p = new Parameters(); StringBuffer sql = new StringBuffer(); sql.append("select distinct e from Experimenter e " + "left outer join fetch e.groupExperimenterMap m " + "left outer join fetch m.parent g where 1=1 "); if (!inactive) { sql.append(" and g.id = :active "); p.addLong("active", helper.getServiceFactory().getAdminService() .getSecurityRoles().getUserGroupId()); } if (!everyone) { if (groupIds.size() > 0) { sql.append(" and e.id in "); sql.append(" (select m.child from GroupExperimenterMap m " + " where m.parent.id in (:gids) )"); p.addSet("gids", new HashSet<Long>(groupIds)); } if (userIds.size() > 0) { if (groupIds.size() > 0) { sql.append(" or "); } else { sql.append(" and "); } sql.append(" e.id in (:eids)"); p.addSet("eids", new HashSet<Long>(userIds)); } } IQuery iquery = helper.getServiceFactory().getQueryService(); List<Experimenter> exps = iquery.findAllByQuery(sql.toString(), p); Set<String> recipients = new HashSet<String>(); for (final Experimenter e : exps) { if (e.getEmail() != null && mailUtil.validateEmail(e.getEmail())) { recipients.add(e.getEmail()); } else { rsp.invalidusers.add(e.getId()); } } return new ArrayList<String>(recipients); } private List<String> parseExtraRecipients() { Set<String> extraRecipients = new HashSet<String>(); for (final String e : extra) { if (mailUtil.validateEmail(e)) { extraRecipients.add(e); } else { rsp.invalidemails.add(e); } } return new ArrayList<String>(extraRecipients); } }