| 1 | package fr.sii.ogham.email.sendgrid.v4.sender.impl; | |
| 2 | ||
| 3 | import static fr.sii.ogham.core.util.LogUtils.logString; | |
| 4 | import static fr.sii.ogham.email.sendgrid.SendGridConstants.DEFAULT_SENDGRID_IMPLEMENTATION_PRIORITY; | |
| 5 | import static fr.sii.ogham.email.sendgrid.sender.EmailValidator.validate; | |
| 6 | ||
| 7 | import java.io.ByteArrayInputStream; | |
| 8 | import java.io.IOException; | |
| 9 | import java.util.regex.Pattern; | |
| 10 | ||
| 11 | import org.slf4j.Logger; | |
| 12 | import org.slf4j.LoggerFactory; | |
| 13 | ||
| 14 | import fr.sii.ogham.core.builder.priority.Priority; | |
| 15 | import fr.sii.ogham.core.exception.MessageException; | |
| 16 | import fr.sii.ogham.core.exception.mimetype.MimeTypeDetectionException; | |
| 17 | import fr.sii.ogham.core.mimetype.MimeTypeProvider; | |
| 18 | import fr.sii.ogham.core.sender.AbstractSpecializedSender; | |
| 19 | import fr.sii.ogham.core.util.Base64Utils; | |
| 20 | import fr.sii.ogham.core.util.IOUtils; | |
| 21 | import fr.sii.ogham.email.attachment.Attachment; | |
| 22 | import fr.sii.ogham.email.exception.handler.ContentHandlerException; | |
| 23 | import fr.sii.ogham.email.message.Email; | |
| 24 | import fr.sii.ogham.email.message.EmailAddress; | |
| 25 | import fr.sii.ogham.email.message.Recipient; | |
| 26 | import fr.sii.ogham.email.sendgrid.sender.SendGridSender; | |
| 27 | import fr.sii.ogham.email.sendgrid.sender.exception.AttachmentReadException; | |
| 28 | import fr.sii.ogham.email.sendgrid.sender.exception.SendGridException; | |
| 29 | import fr.sii.ogham.email.sendgrid.v4.sender.impl.sendgrid.client.SendGridClient; | |
| 30 | import fr.sii.ogham.email.sendgrid.v4.sender.impl.sendgrid.client.SendGridInterceptor; | |
| 31 | import fr.sii.ogham.email.sendgrid.v4.sender.impl.sendgrid.compat.AttachmentsCompat; | |
| 32 | import fr.sii.ogham.email.sendgrid.v4.sender.impl.sendgrid.compat.CompatFactory; | |
| 33 | import fr.sii.ogham.email.sendgrid.v4.sender.impl.sendgrid.compat.CompatUtil; | |
| 34 | import fr.sii.ogham.email.sendgrid.v4.sender.impl.sendgrid.compat.MailCompat; | |
| 35 | import fr.sii.ogham.email.sendgrid.v4.sender.impl.sendgrid.compat.PersonalizationCompat; | |
| 36 | import fr.sii.ogham.email.sendgrid.v4.sender.impl.sendgrid.handler.SendGridContentHandler; | |
| 37 | ||
| 38 | /** | |
| 39 | * SendGrid-backed implementation of the email sender. | |
| 40 | */ | |
| 41 | @Priority(properties = "${ogham.email.implementation-priority.sendgrid}", defaultValue = DEFAULT_SENDGRID_IMPLEMENTATION_PRIORITY) | |
| 42 | public final class SendGridV4Sender extends AbstractSpecializedSender<Email> implements SendGridSender { | |
| 43 | private static final Logger LOG = LoggerFactory.getLogger(SendGridV4Sender.class); | |
| 44 | private static final Pattern CID = Pattern.compile("^<(.+)>$"); | |
| 45 | ||
| 46 | private final SendGridClient delegate; | |
| 47 | private final SendGridContentHandler handler; | |
| 48 | private final MimeTypeProvider mimetypeProvider; | |
| 49 | private final CompatFactory objectsFactory; | |
| 50 | private final SendGridInterceptor interceptor; | |
| 51 | ||
| 52 | /** | |
| 53 | * Uses the default {@link CompatFactory} ({@link CompatUtil#getDefaultCompatFactory()}). | |
| 54 | * | |
| 55 | * @param service | |
| 56 | * the underlying SendGrid service | |
| 57 | * @param handler | |
| 58 | * the content handler, in change of converting the email content | |
| 59 | * into something the {@link SendGridClient} can work with | |
| 60 | * @param mimetypeProvider | |
| 61 | * determines mimetype for attachments | |
| 62 | */ | |
| 63 | public SendGridV4Sender(final SendGridClient service, final SendGridContentHandler handler, MimeTypeProvider mimetypeProvider) { | |
| 64 | this(service, handler, mimetypeProvider, CompatUtil.getDefaultCompatFactory(), null); | |
| 65 | } | |
| 66 | ||
| 67 | /** | |
| 68 | * Constructor. | |
| 69 | * | |
| 70 | * @param service | |
| 71 | * the underlying SendGrid service | |
| 72 | * @param handler | |
| 73 | * the content handler, in change of converting the email content | |
| 74 | * into something the {@link SendGridClient} can work with | |
| 75 | * @param mimetypeProvider | |
| 76 | * determines mimetype for attachments | |
| 77 | * @param objectsFactory | |
| 78 | * factory that creates instances of {@code sendgrid-java} | |
| 79 | * objects. This is needed due to issue in package naming with | |
| 80 | * {@code sendgrid-java} 4.3.0 | |
| 81 | */ | |
| 82 | public SendGridV4Sender(final SendGridClient service, final SendGridContentHandler handler, MimeTypeProvider mimetypeProvider, CompatFactory objectsFactory) { | |
| 83 | this(service, handler, mimetypeProvider, objectsFactory, null); | |
| 84 | } | |
| 85 | ||
| 86 | /** | |
| 87 | * Constructor. | |
| 88 | * | |
| 89 | * @param service | |
| 90 | * the underlying SendGrid service | |
| 91 | * @param handler | |
| 92 | * the content handler, in change of converting the email content | |
| 93 | * into something the {@link SendGridClient} can work with | |
| 94 | * @param mimetypeProvider | |
| 95 | * determines mimetype for attachments | |
| 96 | * @param interceptor | |
| 97 | * an extension point for customizing the email to send | |
| 98 | * @param objectsFactory | |
| 99 | * factory that creates instances of {@code sendgrid-java} | |
| 100 | * objects. This is needed due to issue in package naming with | |
| 101 | * {@code sendgrid-java} 4.3.0 | |
| 102 | */ | |
| 103 | public SendGridV4Sender(final SendGridClient service, final SendGridContentHandler handler, MimeTypeProvider mimetypeProvider, CompatFactory objectsFactory, SendGridInterceptor interceptor) { | |
| 104 |
4
1. <init> : negated conditional → NO_COVERAGE 2. <init> : negated conditional → KILLED 3. <init> : negated conditional → KILLED 4. <init> : negated conditional → KILLED |
if (service == null) { |
| 105 | throw new IllegalArgumentException("[service] cannot be null"); | |
| 106 | } | |
| 107 |
4
1. <init> : negated conditional → NO_COVERAGE 2. <init> : negated conditional → KILLED 3. <init> : negated conditional → KILLED 4. <init> : negated conditional → KILLED |
if (handler == null) { |
| 108 | throw new IllegalArgumentException("[handler] cannot be null"); | |
| 109 | } | |
| 110 |
4
1. <init> : negated conditional → NO_COVERAGE 2. <init> : negated conditional → KILLED 3. <init> : negated conditional → KILLED 4. <init> : negated conditional → KILLED |
if (mimetypeProvider == null) { |
| 111 | throw new IllegalArgumentException("[mimetypeProvider] cannot be null"); | |
| 112 | } | |
| 113 | ||
| 114 | this.delegate = service; | |
| 115 | this.handler = handler; | |
| 116 | this.mimetypeProvider = mimetypeProvider; | |
| 117 | this.objectsFactory = objectsFactory; | |
| 118 | this.interceptor = interceptor; | |
| 119 | } | |
| 120 | ||
| 121 | @Override | |
| 122 | public void send(final Email message) throws MessageException { | |
| 123 |
3
1. send : negated conditional → NO_COVERAGE 2. send : negated conditional → KILLED 3. send : negated conditional → KILLED |
if (message == null) { |
| 124 | throw new IllegalArgumentException("[message] cannot be null"); | |
| 125 | } | |
| 126 |
3
1. send : removed call to fr/sii/ogham/email/sendgrid/sender/EmailValidator::validate → NO_COVERAGE 2. send : removed call to fr/sii/ogham/email/sendgrid/sender/EmailValidator::validate → KILLED 3. send : removed call to fr/sii/ogham/email/sendgrid/sender/EmailValidator::validate → KILLED |
validate(message); |
| 127 | ||
| 128 | try { | |
| 129 | LOG.debug("Preparing to send email using SendGrid: {}", message); | |
| 130 | final MailCompat sgEmail = intercept(toSendGridEmail(message), message); | |
| 131 | ||
| 132 | LOG.debug("Sending email {}", logString(message)); | |
| 133 | LOG.trace("SendGrid email: {}", sgEmail); | |
| 134 |
2
1. send : removed call to fr/sii/ogham/email/sendgrid/v4/sender/impl/sendgrid/client/SendGridClient::send → NO_COVERAGE 2. send : removed call to fr/sii/ogham/email/sendgrid/v4/sender/impl/sendgrid/client/SendGridClient::send → KILLED |
delegate.send(sgEmail); |
| 135 | LOG.debug("Email has been successfully sent"); | |
| 136 | } catch (ContentHandlerException e) { | |
| 137 | throw new MessageException("A content-related error occurred when trying to build an email", message, e); | |
| 138 | } catch (AttachmentReadException e) { | |
| 139 | throw new MessageException("Attaching file to email failed when trying to send an email", message, e); | |
| 140 | } catch (SendGridException e) { | |
| 141 | throw new MessageException("A SendGrid-related error occurred when trying to send an email", message, e); | |
| 142 | } | |
| 143 | } | |
| 144 | ||
| 145 | private MailCompat intercept(MailCompat sendGridEmail, Email source) { | |
| 146 |
2
1. intercept : negated conditional → NO_COVERAGE 2. intercept : negated conditional → KILLED |
if (interceptor == null) { |
| 147 |
2
1. intercept : replaced return value with null for fr/sii/ogham/email/sendgrid/v4/sender/impl/SendGridV4Sender::intercept → NO_COVERAGE 2. intercept : replaced return value with null for fr/sii/ogham/email/sendgrid/v4/sender/impl/SendGridV4Sender::intercept → KILLED |
return sendGridEmail; |
| 148 | } | |
| 149 |
1
1. intercept : replaced return value with null for fr/sii/ogham/email/sendgrid/v4/sender/impl/SendGridV4Sender::intercept → NO_COVERAGE |
return interceptor.intercept(sendGridEmail, source); |
| 150 | } | |
| 151 | ||
| 152 | private MailCompat toSendGridEmail(final Email message) throws ContentHandlerException, AttachmentReadException { | |
| 153 | final MailCompat sendGridMail = objectsFactory.newMail(); | |
| 154 |
2
1. toSendGridEmail : removed call to fr/sii/ogham/email/sendgrid/v4/sender/impl/sendgrid/compat/MailCompat::setSubject → NO_COVERAGE 2. toSendGridEmail : removed call to fr/sii/ogham/email/sendgrid/v4/sender/impl/sendgrid/compat/MailCompat::setSubject → KILLED |
sendGridMail.setSubject(message.getSubject()); |
| 155 | ||
| 156 |
2
1. toSendGridEmail : removed call to fr/sii/ogham/email/sendgrid/v4/sender/impl/sendgrid/compat/MailCompat::setFrom → NO_COVERAGE 2. toSendGridEmail : removed call to fr/sii/ogham/email/sendgrid/v4/sender/impl/sendgrid/compat/MailCompat::setFrom → KILLED |
sendGridMail.setFrom(message.getFrom().getAddress(), message.getFrom().getPersonal()); |
| 157 | ||
| 158 |
2
1. toSendGridEmail : removed call to fr/sii/ogham/email/sendgrid/v4/sender/impl/sendgrid/compat/MailCompat::addPersonalization → NO_COVERAGE 2. toSendGridEmail : removed call to fr/sii/ogham/email/sendgrid/v4/sender/impl/sendgrid/compat/MailCompat::addPersonalization → KILLED |
sendGridMail.addPersonalization(toPersonalization(message)); |
| 159 | ||
| 160 |
2
1. toSendGridEmail : removed call to fr/sii/ogham/email/sendgrid/v4/sender/impl/sendgrid/handler/SendGridContentHandler::setContent → NO_COVERAGE 2. toSendGridEmail : removed call to fr/sii/ogham/email/sendgrid/v4/sender/impl/sendgrid/handler/SendGridContentHandler::setContent → KILLED |
handler.setContent(message, sendGridMail, message.getContent()); |
| 161 | ||
| 162 | for (Attachment attachment : message.getAttachments()) { | |
| 163 |
2
1. toSendGridEmail : removed call to fr/sii/ogham/email/sendgrid/v4/sender/impl/SendGridV4Sender::addAttachment → NO_COVERAGE 2. toSendGridEmail : removed call to fr/sii/ogham/email/sendgrid/v4/sender/impl/SendGridV4Sender::addAttachment → KILLED |
addAttachment(sendGridMail, attachment); |
| 164 | } | |
| 165 | ||
| 166 |
2
1. toSendGridEmail : replaced return value with null for fr/sii/ogham/email/sendgrid/v4/sender/impl/SendGridV4Sender::toSendGridEmail → NO_COVERAGE 2. toSendGridEmail : replaced return value with null for fr/sii/ogham/email/sendgrid/v4/sender/impl/SendGridV4Sender::toSendGridEmail → KILLED |
return sendGridMail; |
| 167 | } | |
| 168 | ||
| 169 | private PersonalizationCompat toPersonalization(final Email message) { | |
| 170 | PersonalizationCompat personalization = objectsFactory.newPersonalization(); | |
| 171 | for (Recipient recipient : message.getRecipients()) { | |
| 172 |
2
1. toPersonalization : removed call to fr/sii/ogham/email/sendgrid/v4/sender/impl/SendGridV4Sender::addRecipient → NO_COVERAGE 2. toPersonalization : removed call to fr/sii/ogham/email/sendgrid/v4/sender/impl/SendGridV4Sender::addRecipient → KILLED |
addRecipient(personalization, recipient); |
| 173 | } | |
| 174 |
2
1. toPersonalization : replaced return value with null for fr/sii/ogham/email/sendgrid/v4/sender/impl/SendGridV4Sender::toPersonalization → NO_COVERAGE 2. toPersonalization : replaced return value with null for fr/sii/ogham/email/sendgrid/v4/sender/impl/SendGridV4Sender::toPersonalization → KILLED |
return personalization; |
| 175 | } | |
| 176 | ||
| 177 | private static void addRecipient(PersonalizationCompat personalization, Recipient recipient) { | |
| 178 | final EmailAddress address = recipient.getAddress(); | |
| 179 | switch (recipient.getType()) { | |
| 180 | case TO: | |
| 181 |
2
1. addRecipient : removed call to fr/sii/ogham/email/sendgrid/v4/sender/impl/sendgrid/compat/PersonalizationCompat::addTo → NO_COVERAGE 2. addRecipient : removed call to fr/sii/ogham/email/sendgrid/v4/sender/impl/sendgrid/compat/PersonalizationCompat::addTo → KILLED |
personalization.addTo(address.getAddress(), address.getPersonal()); |
| 182 | break; | |
| 183 | case CC: | |
| 184 |
1
1. addRecipient : removed call to fr/sii/ogham/email/sendgrid/v4/sender/impl/sendgrid/compat/PersonalizationCompat::addCc → NO_COVERAGE |
personalization.addCc(address.getAddress(), address.getPersonal()); |
| 185 | break; | |
| 186 | case BCC: | |
| 187 |
1
1. addRecipient : removed call to fr/sii/ogham/email/sendgrid/v4/sender/impl/sendgrid/compat/PersonalizationCompat::addBcc → NO_COVERAGE |
personalization.addBcc(address.getAddress(), address.getPersonal()); |
| 188 | break; | |
| 189 | } | |
| 190 | } | |
| 191 | ||
| 192 | private void addAttachment(final MailCompat sendGridMail, final Attachment attachment) throws AttachmentReadException { | |
| 193 | try { | |
| 194 | AttachmentsCompat sendGridAttachment = objectsFactory.newAttachments(); | |
| 195 | byte[] bytes = IOUtils.toByteArray(attachment.getResource().getInputStream()); | |
| 196 |
2
1. addAttachment : removed call to fr/sii/ogham/email/sendgrid/v4/sender/impl/sendgrid/compat/AttachmentsCompat::setContent → NO_COVERAGE 2. addAttachment : removed call to fr/sii/ogham/email/sendgrid/v4/sender/impl/sendgrid/compat/AttachmentsCompat::setContent → KILLED |
sendGridAttachment.setContent(Base64Utils.encodeToString(bytes)); |
| 197 |
2
1. addAttachment : removed call to fr/sii/ogham/email/sendgrid/v4/sender/impl/sendgrid/compat/AttachmentsCompat::setContentId → SURVIVED 2. addAttachment : removed call to fr/sii/ogham/email/sendgrid/v4/sender/impl/sendgrid/compat/AttachmentsCompat::setContentId → NO_COVERAGE |
sendGridAttachment.setContentId(toCid(attachment.getContentId())); |
| 198 |
2
1. addAttachment : removed call to fr/sii/ogham/email/sendgrid/v4/sender/impl/sendgrid/compat/AttachmentsCompat::setDisposition → NO_COVERAGE 2. addAttachment : removed call to fr/sii/ogham/email/sendgrid/v4/sender/impl/sendgrid/compat/AttachmentsCompat::setDisposition → KILLED |
sendGridAttachment.setDisposition(attachment.getDisposition()); |
| 199 |
2
1. addAttachment : removed call to fr/sii/ogham/email/sendgrid/v4/sender/impl/sendgrid/compat/AttachmentsCompat::setFilename → NO_COVERAGE 2. addAttachment : removed call to fr/sii/ogham/email/sendgrid/v4/sender/impl/sendgrid/compat/AttachmentsCompat::setFilename → KILLED |
sendGridAttachment.setFilename(attachment.getResource().getName()); |
| 200 |
2
1. addAttachment : removed call to fr/sii/ogham/email/sendgrid/v4/sender/impl/sendgrid/compat/AttachmentsCompat::setType → NO_COVERAGE 2. addAttachment : removed call to fr/sii/ogham/email/sendgrid/v4/sender/impl/sendgrid/compat/AttachmentsCompat::setType → KILLED |
sendGridAttachment.setType(getMimetype(attachment, bytes)); |
| 201 |
2
1. addAttachment : removed call to fr/sii/ogham/email/sendgrid/v4/sender/impl/sendgrid/compat/MailCompat::addAttachments → NO_COVERAGE 2. addAttachment : removed call to fr/sii/ogham/email/sendgrid/v4/sender/impl/sendgrid/compat/MailCompat::addAttachments → KILLED |
sendGridMail.addAttachments(sendGridAttachment); |
| 202 | } catch (IOException e) { | |
| 203 | throw new AttachmentReadException("Failed to attach email attachment named " + attachment.getResource().getName(), attachment, e); | |
| 204 | } catch (MimeTypeDetectionException e) { | |
| 205 | throw new AttachmentReadException("Failed to determine mimetype for email attachment named " + attachment.getResource().getName(), attachment, e); | |
| 206 | } | |
| 207 | } | |
| 208 | ||
| 209 | private String getMimetype(Attachment attachment, byte[] bytes) throws MimeTypeDetectionException { | |
| 210 |
2
1. getMimetype : negated conditional → NO_COVERAGE 2. getMimetype : negated conditional → KILLED |
if (attachment.getContentType() != null) { |
| 211 |
2
1. getMimetype : replaced return value with "" for fr/sii/ogham/email/sendgrid/v4/sender/impl/SendGridV4Sender::getMimetype → NO_COVERAGE 2. getMimetype : replaced return value with "" for fr/sii/ogham/email/sendgrid/v4/sender/impl/SendGridV4Sender::getMimetype → KILLED |
return attachment.getContentType(); |
| 212 | } | |
| 213 |
2
1. getMimetype : replaced return value with "" for fr/sii/ogham/email/sendgrid/v4/sender/impl/SendGridV4Sender::getMimetype → NO_COVERAGE 2. getMimetype : replaced return value with "" for fr/sii/ogham/email/sendgrid/v4/sender/impl/SendGridV4Sender::getMimetype → KILLED |
return mimetypeProvider.detect(new ByteArrayInputStream(bytes)).toString(); |
| 214 | } | |
| 215 | ||
| 216 | private static String toCid(final String contentId) { | |
| 217 |
2
1. toCid : negated conditional → NO_COVERAGE 2. toCid : negated conditional → KILLED |
if (contentId == null) { |
| 218 |
2
1. toCid : replaced return value with "" for fr/sii/ogham/email/sendgrid/v4/sender/impl/SendGridV4Sender::toCid → SURVIVED 2. toCid : replaced return value with "" for fr/sii/ogham/email/sendgrid/v4/sender/impl/SendGridV4Sender::toCid → NO_COVERAGE |
return null; |
| 219 | } | |
| 220 |
1
1. toCid : replaced return value with "" for fr/sii/ogham/email/sendgrid/v4/sender/impl/SendGridV4Sender::toCid → NO_COVERAGE |
return CID.matcher(contentId).replaceAll("$1"); |
| 221 | } | |
| 222 | ||
| 223 | public SendGridClient getDelegate() { | |
| 224 |
1
1. getDelegate : replaced return value with null for fr/sii/ogham/email/sendgrid/v4/sender/impl/SendGridV4Sender::getDelegate → NO_COVERAGE |
return delegate; |
| 225 | } | |
| 226 | } | |
Mutations | ||
| 104 |
1.1 2.2 3.3 4.4 |
|
| 107 |
1.1 2.2 3.3 4.4 |
|
| 110 |
1.1 2.2 3.3 4.4 |
|
| 123 |
1.1 2.2 3.3 |
|
| 126 |
1.1 2.2 3.3 |
|
| 134 |
1.1 2.2 |
|
| 146 |
1.1 2.2 |
|
| 147 |
1.1 2.2 |
|
| 149 |
1.1 |
|
| 154 |
1.1 2.2 |
|
| 156 |
1.1 2.2 |
|
| 158 |
1.1 2.2 |
|
| 160 |
1.1 2.2 |
|
| 163 |
1.1 2.2 |
|
| 166 |
1.1 2.2 |
|
| 172 |
1.1 2.2 |
|
| 174 |
1.1 2.2 |
|
| 181 |
1.1 2.2 |
|
| 184 |
1.1 |
|
| 187 |
1.1 |
|
| 196 |
1.1 2.2 |
|
| 197 |
1.1 2.2 |
|
| 198 |
1.1 2.2 |
|
| 199 |
1.1 2.2 |
|
| 200 |
1.1 2.2 |
|
| 201 |
1.1 2.2 |
|
| 210 |
1.1 2.2 |
|
| 211 |
1.1 2.2 |
|
| 213 |
1.1 2.2 |
|
| 217 |
1.1 2.2 |
|
| 218 |
1.1 2.2 |
|
| 220 |
1.1 |
|
| 224 |
1.1 |