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 |