| 1 | package fr.sii.ogham.email.builder; | |
| 2 | ||
| 3 | import org.slf4j.Logger; | |
| 4 | import org.slf4j.LoggerFactory; | |
| 5 | ||
| 6 | import fr.sii.ogham.core.async.Awaiter; | |
| 7 | import fr.sii.ogham.core.builder.ActivableAtRuntime; | |
| 8 | import fr.sii.ogham.core.builder.Builder; | |
| 9 | import fr.sii.ogham.core.builder.MessagingBuilder; | |
| 10 | import fr.sii.ogham.core.builder.condition.RequiredClass; | |
| 11 | import fr.sii.ogham.core.builder.condition.RequiredClasses; | |
| 12 | import fr.sii.ogham.core.builder.condition.RequiredProperties; | |
| 13 | import fr.sii.ogham.core.builder.condition.RequiredProperty; | |
| 14 | import fr.sii.ogham.core.builder.configuration.ConfigurationValueBuilder; | |
| 15 | import fr.sii.ogham.core.builder.configuration.ConfigurationValueBuilderDelegate; | |
| 16 | import fr.sii.ogham.core.builder.configurer.Configurer; | |
| 17 | import fr.sii.ogham.core.builder.configurer.MessagingConfigurer; | |
| 18 | import fr.sii.ogham.core.builder.context.BuildContext; | |
| 19 | import fr.sii.ogham.core.builder.env.EnvironmentBuilder; | |
| 20 | import fr.sii.ogham.core.builder.retry.RetryBuilder; | |
| 21 | import fr.sii.ogham.core.builder.sender.SenderImplementationBuilderHelper; | |
| 22 | import fr.sii.ogham.core.builder.template.DetectorBuilder; | |
| 23 | import fr.sii.ogham.core.builder.template.TemplateBuilderHelper; | |
| 24 | import fr.sii.ogham.core.builder.template.VariantBuilder; | |
| 25 | import fr.sii.ogham.core.condition.Condition; | |
| 26 | import fr.sii.ogham.core.condition.fluent.MessageConditions; | |
| 27 | import fr.sii.ogham.core.filler.MessageFiller; | |
| 28 | import fr.sii.ogham.core.fluent.AbstractParent; | |
| 29 | import fr.sii.ogham.core.message.content.MultiTemplateContent; | |
| 30 | import fr.sii.ogham.core.message.content.Variant; | |
| 31 | import fr.sii.ogham.core.retry.ExponentialDelayRetry; | |
| 32 | import fr.sii.ogham.core.retry.FixedDelayRetry; | |
| 33 | import fr.sii.ogham.core.retry.FixedIntervalRetry; | |
| 34 | import fr.sii.ogham.core.retry.PerExecutionDelayRetry; | |
| 35 | import fr.sii.ogham.core.retry.RetryExecutor; | |
| 36 | import fr.sii.ogham.core.sender.AutoRetrySender; | |
| 37 | import fr.sii.ogham.core.sender.ConditionalSender; | |
| 38 | import fr.sii.ogham.core.sender.ContentTranslatorSender; | |
| 39 | import fr.sii.ogham.core.sender.FillerSender; | |
| 40 | import fr.sii.ogham.core.sender.MessageSender; | |
| 41 | import fr.sii.ogham.core.template.parser.TemplateParser; | |
| 42 | import fr.sii.ogham.core.translator.content.ContentTranslator; | |
| 43 | import fr.sii.ogham.core.translator.content.EveryContentTranslator; | |
| 44 | import fr.sii.ogham.core.translator.content.MultiContentTranslator; | |
| 45 | import fr.sii.ogham.core.translator.content.TemplateContentTranslator; | |
| 46 | import fr.sii.ogham.core.translator.resource.AttachmentResourceTranslator; | |
| 47 | import fr.sii.ogham.core.util.BuilderUtils; | |
| 48 | import fr.sii.ogham.email.attachment.Attachment; | |
| 49 | import fr.sii.ogham.email.message.Email; | |
| 50 | import fr.sii.ogham.email.sender.AttachmentResourceTranslatorSender; | |
| 51 | import fr.sii.ogham.email.sender.EmailSender; | |
| 52 | import fr.sii.ogham.template.common.adapter.VariantResolver; | |
| 53 | ||
| 54 | /** | |
| 55 | * Configures how to send {@link Email} messages. It allows to: | |
| 56 | * <ul> | |
| 57 | * <li>register and configure several sender implementations</li> | |
| 58 | * <li>register and configure several template engines for parsing templates as | |
| 59 | * message content</li> | |
| 60 | * <li>configure handling of missing {@link Email} information</li> | |
| 61 | * <li>configure handling of file attachments</li> | |
| 62 | * <li>configure CSS and image handling for {@link Email}s with an HTML | |
| 63 | * body</li> | |
| 64 | * </ul> | |
| 65 | * | |
| 66 | * You can send an {@link Email} using the minimal behavior and using JavaMail | |
| 67 | * implementation: | |
| 68 | * | |
| 69 | * <pre> | |
| 70 | * <code> | |
| 71 | * // Instantiate the messaging service | |
| 72 | * MessagingService service = new MessagingBuilder() | |
| 73 | * .email() | |
| 74 | * .sender(JavaMailBuilder.class) // enable Email sending using JavaMail | |
| 75 | * .host("your SMTP server host") | |
| 76 | * .port("your SMTP server port") | |
| 77 | * .and() | |
| 78 | * .and() | |
| 79 | * .build(); | |
| 80 | * // send the email | |
| 81 | * service.send(new Email() | |
| 82 | * .from("sender email address") | |
| 83 | * .subject("email subject") | |
| 84 | * .content("email body") | |
| 85 | * .to("recipient email address")); | |
| 86 | * </code> | |
| 87 | * </pre> | |
| 88 | * | |
| 89 | * You can also send an {@link Email} using a template (using Freemarker for | |
| 90 | * example): | |
| 91 | * | |
| 92 | * The Freemarker template ("email/sample.html.ftl"): | |
| 93 | * | |
| 94 | * <pre> | |
| 95 | * <html> | |
| 96 | * <head> | |
| 97 | * </head> | |
| 98 | * <body> | |
| 99 | * Email content with variables: ${name} ${value} | |
| 100 | * </body> | |
| 101 | * </html> | |
| 102 | * </pre> | |
| 103 | * | |
| 104 | * Then you can send the {@link Email} like this: | |
| 105 | * | |
| 106 | * <pre> | |
| 107 | * <code> | |
| 108 | * // Instantiate the messaging service | |
| 109 | * MessagingService service = new MessagingBuilder() | |
| 110 | * .email() | |
| 111 | * .sender(JavaMailBuilder.class) // enable Email sending using JavaMail | |
| 112 | * .host("your SMTP server host") | |
| 113 | * .port("your SMTP server port") | |
| 114 | * .and() | |
| 115 | * .and() | |
| 116 | * .template(FreemarkerEmailBuilder.class) // enable templating using Freemarker | |
| 117 | * .classpath() | |
| 118 | * .lookup("classpath:") // search resources/templates in the classpath if a path is prefixed by "classpath:" | |
| 119 | * .and() | |
| 120 | * .and() | |
| 121 | * .build(); | |
| 122 | * // send the email | |
| 123 | * service.send(new Email() | |
| 124 | * .from("sender email address") | |
| 125 | * .subject("email subject") | |
| 126 | * .content(new TemplateContent("classpath:email/sample.html.ftl", new SampleBean("foo", 42))) | |
| 127 | * .to("recipient email address")); | |
| 128 | * </code> | |
| 129 | * </pre> | |
| 130 | * | |
| 131 | * <p> | |
| 132 | * Instead of explicitly configures SMTP host and port in your code, it could be | |
| 133 | * better to externalize the configuration in a properties file for example (for | |
| 134 | * example a file named "email.properties" in the classpath). The previous | |
| 135 | * example becomes: | |
| 136 | * | |
| 137 | * <pre> | |
| 138 | * <code> | |
| 139 | * // Instantiate the messaging service | |
| 140 | * MessagingService service = new MessagingBuilder() | |
| 141 | * .environment() | |
| 142 | * .properties("email.properties") | |
| 143 | * .and() | |
| 144 | * .email() | |
| 145 | * .sender(JavaMailBuilder.class) // enable Email sending using JavaMail | |
| 146 | * .host("${mail.host}") | |
| 147 | * .port("${mail.port}") | |
| 148 | * .and() | |
| 149 | * .and() | |
| 150 | * .template(FreemarkerEmailBuilder.class) // enable templating using Freemarker | |
| 151 | * .classpath() | |
| 152 | * .lookup("classpath:") // search resources/templates in the classpath if a path is prefixed by "classpath:" | |
| 153 | * .and() | |
| 154 | * .and() | |
| 155 | * .build(); | |
| 156 | * // send the email | |
| 157 | * service.send(new Email() | |
| 158 | * .from("sender email address") | |
| 159 | * .subject("email subject") | |
| 160 | * .content(new TemplateContent("classpath:email/sample.html.ftl", new SampleBean("foo", 42))) | |
| 161 | * .to("recipient email address")); | |
| 162 | * </code> | |
| 163 | * </pre> | |
| 164 | * | |
| 165 | * The content of the file "email.properties": | |
| 166 | * | |
| 167 | * <pre> | |
| 168 | * mail.host=your STMP server host | |
| 169 | * mail.port=your STMP server port | |
| 170 | * </pre> | |
| 171 | * | |
| 172 | * | |
| 173 | * Some fields of the Email may be automatically filled by a default value if | |
| 174 | * they are not defined. For example, the sender address could be configured | |
| 175 | * only once for your application: | |
| 176 | * | |
| 177 | * <pre> | |
| 178 | * <code> | |
| 179 | * // Instantiate the messaging service | |
| 180 | * MessagingService service = new MessagingBuilder() | |
| 181 | * .environment() | |
| 182 | * .properties("email.properties") | |
| 183 | * .and() | |
| 184 | * .email() | |
| 185 | * .sender(JavaMailBuilder.class) // enable Email sending using JavaMail | |
| 186 | * .host("${mail.host}") | |
| 187 | * .port("${mail.port}") | |
| 188 | * .and() | |
| 189 | * .autofill() // enables and configures autofilling | |
| 190 | * .from() | |
| 191 | * .defaultValue().properties("${email.sender.address}") | |
| 192 | * .and() | |
| 193 | * .and() | |
| 194 | * .template(FreemarkerEmailBuilder.class) // enable templating using Freemarker | |
| 195 | * .classpath() | |
| 196 | * .lookup("classpath:") // search resources/templates in the classpath if a path is prefixed by "classpath:" | |
| 197 | * .and() | |
| 198 | * .and() | |
| 199 | * .build(); | |
| 200 | * // send the email (now the sender address can be omitted) | |
| 201 | * service.send(new Email() | |
| 202 | * .subject("email subject") | |
| 203 | * .content(new TemplateContent("classpath:email/sample.html.ftl", new SampleBean("foo", 42))) | |
| 204 | * .to("recipient email address")); | |
| 205 | * </code> | |
| 206 | * </pre> | |
| 207 | * | |
| 208 | * The content of the file "email.properties": | |
| 209 | * | |
| 210 | * <pre> | |
| 211 | * mail.host=your STMP server host | |
| 212 | * mail.port=your STMP server port | |
| 213 | * email.sender.address=sender email address | |
| 214 | * </pre> | |
| 215 | * | |
| 216 | * | |
| 217 | * | |
| 218 | * Another very useful automatic filling is for providing the email subject: | |
| 219 | * | |
| 220 | * <pre> | |
| 221 | * <code> | |
| 222 | * // Instantiate the messaging service | |
| 223 | * MessagingService service = new MessagingBuilder() | |
| 224 | * .environment() | |
| 225 | * .properties("email.properties") | |
| 226 | * .and() | |
| 227 | * .email() | |
| 228 | * .sender(JavaMailBuilder.class) // enable Email sending using JavaMail | |
| 229 | * .host("${mail.host}") | |
| 230 | * .port("${mail.port}") | |
| 231 | * .and() | |
| 232 | * .autofill() // enables and configures autofilling | |
| 233 | * .from() | |
| 234 | * .defaultValue().properties("${email.sender.address}").and() | |
| 235 | * .and() | |
| 236 | * .subject() | |
| 237 | * .htmlTitle(true) // enables use of html title tag as subject | |
| 238 | * .and() | |
| 239 | * .template(FreemarkerEmailBuilder.class) // enable templating using Freemarker | |
| 240 | * .classpath() | |
| 241 | * .lookup("classpath:") // search resources/templates in the classpath if a path is prefixed by "classpath:" | |
| 242 | * .and() | |
| 243 | * .and() | |
| 244 | * .build(); | |
| 245 | * // send the email (now the subject can be omitted) | |
| 246 | * service.send(new Email() | |
| 247 | * .content(new TemplateContent("classpath:email/sample.html.ftl", new SampleBean("foo", 42))) | |
| 248 | * .to("recipient email address")); | |
| 249 | * </code> | |
| 250 | * </pre> | |
| 251 | * | |
| 252 | * Change your template: | |
| 253 | * | |
| 254 | * <pre> | |
| 255 | * <html> | |
| 256 | * <head> | |
| 257 | * <title>email subject - ${name}</title> | |
| 258 | * </head> | |
| 259 | * <body> | |
| 260 | * Email content with variables: ${name} ${value} | |
| 261 | * </body> | |
| 262 | * </html> | |
| 263 | * </pre> | |
| 264 | * | |
| 265 | * The obvious advantage is that you have a single place to handle email content | |
| 266 | * (body + subject). There is another benefit: you can also use variables in the | |
| 267 | * subject. | |
| 268 | * | |
| 269 | * | |
| 270 | * There many other configuration possibilities: | |
| 271 | * <ul> | |
| 272 | * <li>for configuring {@link Email}s with HTML content with a text fallback | |
| 273 | * (useful for smartphones preview of your email for example)</li> | |
| 274 | * <li>for configuring attachments handling</li> | |
| 275 | * <li>for configuring image and css handling</li> | |
| 276 | * </ul> | |
| 277 | * | |
| 278 | * <p> | |
| 279 | * All the previous examples are provided to understand what can be configured. | |
| 280 | * Hopefully, Ogham provides auto-configuration with a default behavior that | |
| 281 | * fits 95% of usages. This auto-configuration is provided by | |
| 282 | * {@link MessagingConfigurer}s. Those configurers are automatically applied | |
| 283 | * when using predefined {@link MessagingBuilder}s like | |
| 284 | * {@link MessagingBuilder#minimal()} and {@link MessagingBuilder#standard()}. | |
| 285 | * | |
| 286 | * The previous sample using standard configuration becomes: | |
| 287 | * | |
| 288 | * <pre> | |
| 289 | * <code> | |
| 290 | * // Instantiate the messaging service | |
| 291 | * MessagingService service = MessagingBuilder.standad() | |
| 292 | * .environment() | |
| 293 | * .properties("email.properties") | |
| 294 | * .and() | |
| 295 | * .build(); | |
| 296 | * // send the email | |
| 297 | * service.send(new Email() | |
| 298 | * .content(new TemplateContent("classpath:email/sample.html.ftl", new SampleBean("foo", 42))) | |
| 299 | * .to("recipient email address")); | |
| 300 | * </code> | |
| 301 | * </pre> | |
| 302 | * | |
| 303 | * The new content of the file "email.properties": | |
| 304 | * | |
| 305 | * <pre> | |
| 306 | * mail.host=your STMP server host | |
| 307 | * mail.port=your STMP server port | |
| 308 | * ogham.email.from.default-value=sender email address | |
| 309 | * </pre> | |
| 310 | * | |
| 311 | * <p> | |
| 312 | * You can also use the auto-configuration for benefit from default behaviors | |
| 313 | * and override some behaviors for your needs: | |
| 314 | * | |
| 315 | * <pre> | |
| 316 | * <code> | |
| 317 | * // Instantiate the messaging service | |
| 318 | * MessagingService service = MessagingBuilder.standard() | |
| 319 | * .environment() | |
| 320 | * .properties("email.properties") | |
| 321 | * .and() | |
| 322 | * .email() | |
| 323 | * .autofill() | |
| 324 | * .from() | |
| 325 | * .defaultValue() | |
| 326 | * .properties("${email.sender.address}") // overrides default sender email address property | |
| 327 | * .and() | |
| 328 | * .and() | |
| 329 | * .and() | |
| 330 | * .and() | |
| 331 | * .build(); | |
| 332 | * // send the email | |
| 333 | * service.send(new Email() | |
| 334 | * .content(new TemplateContent("classpath:email/sample.html.ftl", new SampleBean("foo", 42))) | |
| 335 | * .to("recipient email address")); | |
| 336 | * </code> | |
| 337 | * </pre> | |
| 338 | * | |
| 339 | * The new content of the file "email.properties": | |
| 340 | * | |
| 341 | * <pre> | |
| 342 | * mail.host=your STMP server host | |
| 343 | * mail.port=your STMP server port | |
| 344 | * email.sender.address=sender email address | |
| 345 | * </pre> | |
| 346 | * | |
| 347 | * @author Aurélien Baudet | |
| 348 | * | |
| 349 | */ | |
| 350 | public class EmailBuilder extends AbstractParent<MessagingBuilder> implements Builder<ConditionalSender> { | |
| 351 | private static final Logger LOG = LoggerFactory.getLogger(EmailBuilder.class); | |
| 352 | ||
| 353 | private final BuildContext buildContext; | |
| 354 | private final TemplateBuilderHelper<EmailBuilder> templateBuilderHelper; | |
| 355 | private final SenderImplementationBuilderHelper<EmailBuilder> senderBuilderHelper; | |
| 356 | private AttachmentHandlingBuilder attachmentBuilder; | |
| 357 | private AutofillEmailBuilder autofillBuilder; | |
| 358 | private CssHandlingBuilder cssBuilder; | |
| 359 | private ImageHandlingBuilder imageBuilder; | |
| 360 | private RetryBuilder<EmailBuilder> retryBuilder; | |
| 361 | | |
| 362 | /** | |
| 363 | * Initializes the builder with a parent builder. The parent builder is used | |
| 364 | * when calling {@link #and()} method. The {@link EnvironmentBuilder} is | |
| 365 | * used to evaluate properties when {@link #build()} method is called. | |
| 366 | * | |
| 367 | * @param parent | |
| 368 | * the parent builder | |
| 369 | * @param buildContext | |
| 370 | * for registering instances and property evaluation | |
| 371 | */ | |
| 372 | public EmailBuilder(MessagingBuilder parent, BuildContext buildContext) { | |
| 373 | super(parent); | |
| 374 | this.buildContext = buildContext; | |
| 375 | templateBuilderHelper = new TemplateBuilderHelper<>(this, buildContext); | |
| 376 | senderBuilderHelper = new SenderImplementationBuilderHelper<>(this, buildContext); | |
| 377 | } | |
| 378 | ||
| 379 | /** | |
| 380 | * Configures how {@link Attachment}s are handled. | |
| 381 | * | |
| 382 | * Attachment resolution consists of finding a file: | |
| 383 | * <ul> | |
| 384 | * <li>either on filesystem</li> | |
| 385 | * <li>or in the classpath</li> | |
| 386 | * <li>or anywhere else</li> | |
| 387 | * </ul> | |
| 388 | * | |
| 389 | * <p> | |
| 390 | * To identify which resolution to use, each resolution is configured to | |
| 391 | * handle one or several lookups prefixes. For example, if resolution is | |
| 392 | * configured like this: | |
| 393 | * | |
| 394 | * <pre> | |
| 395 | * <code> | |
| 396 | * .string() | |
| 397 | * .lookup("string:", "s:") | |
| 398 | * .and() | |
| 399 | * .file() | |
| 400 | * .lookup("file:") | |
| 401 | * .and() | |
| 402 | * .classpath() | |
| 403 | * .lookup("classpath:", ""); | |
| 404 | * </code> | |
| 405 | * </pre> | |
| 406 | * | |
| 407 | * Then you can reference a file that is in the classpath like this: | |
| 408 | * | |
| 409 | * <pre> | |
| 410 | * "classpath:foo/bar.pdf" | |
| 411 | * </pre> | |
| 412 | * | |
| 413 | * | |
| 414 | * <p> | |
| 415 | * Resource resolution is also able to handle path prefix and suffix. The | |
| 416 | * aim is for example to have a folder that contains all templates. The | |
| 417 | * developer then configures a path prefix for the folder. He can also | |
| 418 | * configure a suffix to fix extension for templates. Thanks to those | |
| 419 | * prefix/suffix, templates can now be referenced by the name of the file | |
| 420 | * (without extension). It is useful to reference a template independently | |
| 421 | * from where it is in reality (classpath, file or anywhere else) . | |
| 422 | * Switching from classpath to file and conversely can be done easily (by | |
| 423 | * updating the lookup). | |
| 424 | * | |
| 425 | * For example: | |
| 426 | * | |
| 427 | * <pre> | |
| 428 | * .classpath().lookup("classpath:").pathPrefix("foo/").pathSuffix(".html"); | |
| 429 | * | |
| 430 | * resourceResolver.getResource("classpath:bar"); | |
| 431 | * </pre> | |
| 432 | * | |
| 433 | * The real path is then {@code foo/bar.pdf}. | |
| 434 | * | |
| 435 | * <p> | |
| 436 | * This implementation is used by {@link MessagingBuilder} for general | |
| 437 | * configuration. That configuration may be inherited (applied to other | |
| 438 | * resource resolution builders). | |
| 439 | * | |
| 440 | * | |
| 441 | * <p> | |
| 442 | * Detection of the mimetype of each attachment is not directly configured | |
| 443 | * here. Attachment handling depends totally on the sender implementation. | |
| 444 | * Some implementations will require that a mimetype is provided (JavaMail | |
| 445 | * for example) while other implementations doesn't need it (SendGrid for | |
| 446 | * example). | |
| 447 | * | |
| 448 | * @return the builder to configure attachment handling | |
| 449 | */ | |
| 450 | public AttachmentHandlingBuilder attachments() { | |
| 451 |
8
1. attachments : negated conditional → NO_COVERAGE 2. attachments : negated conditional → KILLED 3. attachments : negated conditional → KILLED 4. attachments : negated conditional → KILLED 5. attachments : negated conditional → KILLED 6. attachments : negated conditional → KILLED 7. attachments : negated conditional → KILLED 8. attachments : negated conditional → KILLED |
if (attachmentBuilder == null) { |
| 452 | attachmentBuilder = new AttachmentHandlingBuilder(this, buildContext); | |
| 453 | } | |
| 454 |
8
1. attachments : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::attachments → NO_COVERAGE 2. attachments : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::attachments → KILLED 3. attachments : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::attachments → KILLED 4. attachments : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::attachments → KILLED 5. attachments : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::attachments → KILLED 6. attachments : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::attachments → KILLED 7. attachments : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::attachments → KILLED 8. attachments : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::attachments → KILLED |
return attachmentBuilder; |
| 455 | } | |
| 456 | ||
| 457 | /** | |
| 458 | * Configures how Ogham will add default values to the {@link Email} if some | |
| 459 | * information is missing. | |
| 460 | * | |
| 461 | * If sender address is missing, a default one can be defined in | |
| 462 | * configuration properties. | |
| 463 | * | |
| 464 | * If recipient address is missing, a default one can be defined in | |
| 465 | * configuration properties. | |
| 466 | * | |
| 467 | * If subject is missing, a default one can be defined either: | |
| 468 | * <ul> | |
| 469 | * <li>In HTML title</li> | |
| 470 | * <li>In first line of text template</li> | |
| 471 | * <li>Using a default value defined in configuration properties</li> | |
| 472 | * </ul> | |
| 473 | * | |
| 474 | * For example: | |
| 475 | * | |
| 476 | * <pre> | |
| 477 | * <code> | |
| 478 | * builder | |
| 479 | * .autofill() | |
| 480 | * .subject() | |
| 481 | * .defaultValue().properties("${ogham.email.subject.default-value}").and() | |
| 482 | * .htmlTitle(true) | |
| 483 | * .text().properties("${ogham.email.subject.extract-from-text.first-line-prefix}").defaultValue("Subject:").and() | |
| 484 | * .and() | |
| 485 | * .from() | |
| 486 | * .defaultValue().properties("${ogham.email.from.default-value}", "${mail.smtp.from}", "${mail.from}").and() | |
| 487 | * .and() | |
| 488 | * .to() | |
| 489 | * .defaultValue().properties("${ogham.email.to.default-value}").and() | |
| 490 | * .and() | |
| 491 | * .cc() | |
| 492 | * .defaultValue().properties("${ogham.email.cc.default-value}").and() | |
| 493 | * .and() | |
| 494 | * .bcc() | |
| 495 | * .defaultValue().properties("${ogham.email.bcc.default-value}") | |
| 496 | * </code> | |
| 497 | * </pre> | |
| 498 | * | |
| 499 | * @return the builder to configure autofilling of Email | |
| 500 | */ | |
| 501 | public AutofillEmailBuilder autofill() { | |
| 502 |
8
1. autofill : negated conditional → NO_COVERAGE 2. autofill : negated conditional → KILLED 3. autofill : negated conditional → KILLED 4. autofill : negated conditional → KILLED 5. autofill : negated conditional → KILLED 6. autofill : negated conditional → KILLED 7. autofill : negated conditional → KILLED 8. autofill : negated conditional → KILLED |
if (autofillBuilder == null) { |
| 503 | autofillBuilder = new AutofillEmailBuilder(this, buildContext); | |
| 504 | } | |
| 505 |
8
1. autofill : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::autofill → NO_COVERAGE 2. autofill : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::autofill → KILLED 3. autofill : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::autofill → KILLED 4. autofill : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::autofill → KILLED 5. autofill : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::autofill → KILLED 6. autofill : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::autofill → KILLED 7. autofill : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::autofill → KILLED 8. autofill : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::autofill → KILLED |
return autofillBuilder; |
| 506 | } | |
| 507 | ||
| 508 | /** | |
| 509 | * CSS handling consists of defining how CSS are inlined in the email. | |
| 510 | * Inlining CSS means that CSS styles are loaded and applied on the matching | |
| 511 | * HTML nodes using the {@code style} HTML attribute. | |
| 512 | * | |
| 513 | * For example: | |
| 514 | * | |
| 515 | * <pre> | |
| 516 | * .css() | |
| 517 | * .inline() | |
| 518 | * .jsoup() | |
| 519 | * </pre> | |
| 520 | * | |
| 521 | * Enables inlining of CSS styles using Jsoup utility. | |
| 522 | * | |
| 523 | * @return the builder to configure css handling | |
| 524 | */ | |
| 525 | public CssHandlingBuilder css() { | |
| 526 |
8
1. css : negated conditional → NO_COVERAGE 2. css : negated conditional → KILLED 3. css : negated conditional → KILLED 4. css : negated conditional → KILLED 5. css : negated conditional → KILLED 6. css : negated conditional → KILLED 7. css : negated conditional → KILLED 8. css : negated conditional → KILLED |
if (cssBuilder == null) { |
| 527 | cssBuilder = new CssHandlingBuilder(this, buildContext); | |
| 528 | } | |
| 529 |
8
1. css : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::css → NO_COVERAGE 2. css : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::css → KILLED 3. css : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::css → KILLED 4. css : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::css → KILLED 5. css : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::css → KILLED 6. css : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::css → KILLED 7. css : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::css → KILLED 8. css : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::css → KILLED |
return cssBuilder; |
| 530 | } | |
| 531 | ||
| 532 | /** | |
| 533 | * Image handling consists of defining how images are inlined in the email: | |
| 534 | * <ul> | |
| 535 | * <li>Either inlining directly in the HTML content by enconding image into | |
| 536 | * base64 string</li> | |
| 537 | * <li>Or attaching the image to the email and referencing it using a | |
| 538 | * <a href="https://tools.ietf.org/html/rfc4021#section-2.2.2">Content-ID | |
| 539 | * (CID)</a></li> | |
| 540 | * <li>Or no inlining</li> | |
| 541 | * </ul> | |
| 542 | * | |
| 543 | * | |
| 544 | * For example: | |
| 545 | * | |
| 546 | * <pre> | |
| 547 | * .images() | |
| 548 | * .inline() | |
| 549 | * .attach() | |
| 550 | * .cid() | |
| 551 | * .generator(new SequentialIdGenerator()) | |
| 552 | * .and() | |
| 553 | * .and() | |
| 554 | * .base64(); | |
| 555 | * </pre> | |
| 556 | * | |
| 557 | * Enables both inlining modes (attaching images and encoding in base64). By | |
| 558 | * default, attaching is used if nothing is specified in the HTML. You can | |
| 559 | * also explicitly specify which mode to using the {@code data-inline-image} | |
| 560 | * attribute (see {@link ImageHandlingBuilder#inline()} for more | |
| 561 | * information). | |
| 562 | * | |
| 563 | * @return the builder to configure images handling | |
| 564 | */ | |
| 565 | public ImageHandlingBuilder images() { | |
| 566 |
8
1. images : negated conditional → NO_COVERAGE 2. images : negated conditional → KILLED 3. images : negated conditional → KILLED 4. images : negated conditional → KILLED 5. images : negated conditional → KILLED 6. images : negated conditional → KILLED 7. images : negated conditional → KILLED 8. images : negated conditional → KILLED |
if (imageBuilder == null) { |
| 567 | imageBuilder = new ImageHandlingBuilder(this, buildContext); | |
| 568 | } | |
| 569 |
8
1. images : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::images → NO_COVERAGE 2. images : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::images → KILLED 3. images : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::images → KILLED 4. images : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::images → KILLED 5. images : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::images → KILLED 6. images : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::images → KILLED 7. images : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::images → KILLED 8. images : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::images → KILLED |
return imageBuilder; |
| 570 | } | |
| 571 | ||
| 572 | /** | |
| 573 | * Registers and configures a {@link TemplateParser} through a dedicated | |
| 574 | * builder. | |
| 575 | * | |
| 576 | * For example: | |
| 577 | * | |
| 578 | * <pre> | |
| 579 | * .register(ThymeleafEmailBuilder.class) | |
| 580 | * .detector(new ThymeleafEngineDetector()); | |
| 581 | * </pre> | |
| 582 | * | |
| 583 | * <p> | |
| 584 | * Your {@link Builder} may implement {@link VariantBuilder} to handle | |
| 585 | * template {@link Variant}s (used for {@link MultiTemplateContent} that | |
| 586 | * provide a single path to templates with different extensions for | |
| 587 | * example). | |
| 588 | * </p> | |
| 589 | * | |
| 590 | * <p> | |
| 591 | * Your {@link Builder} may also implement {@link DetectorBuilder} in order | |
| 592 | * to indicate which kind of templates your {@link TemplateParser} is able | |
| 593 | * to parse. If your template parse is able to parse any template file you | |
| 594 | * are using, you may not need to implement {@link DetectorBuilder}. | |
| 595 | * </p> | |
| 596 | * | |
| 597 | * <p> | |
| 598 | * In order to be able to keep chaining, you builder instance may provide a | |
| 599 | * constructor with two arguments: | |
| 600 | * <ul> | |
| 601 | * <li>The type of the parent builder ({@code <P>})</li> | |
| 602 | * <li>The {@link EnvironmentBuilder} instance</li> | |
| 603 | * </ul> | |
| 604 | * If you don't care about chaining, just provide a default constructor. | |
| 605 | * | |
| 606 | * @param builderClass | |
| 607 | * the builder class to instantiate | |
| 608 | * @param <T> | |
| 609 | * the type of the builder | |
| 610 | * @return the builder to configure the implementation | |
| 611 | */ | |
| 612 | public <T extends Builder<? extends TemplateParser>> T template(Class<T> builderClass) { | |
| 613 |
5
1. template : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::template → NO_COVERAGE 2. template : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::template → KILLED 3. template : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::template → KILLED 4. template : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::template → KILLED 5. template : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::template → KILLED |
return templateBuilderHelper.register(builderClass); |
| 614 | } | |
| 615 | ||
| 616 | /** | |
| 617 | * Registers a custom message sender implementation. | |
| 618 | * | |
| 619 | * <p> | |
| 620 | * If your custom implementation is annotated by one or several of: | |
| 621 | * <ul> | |
| 622 | * <li>{@link RequiredClass}</li> | |
| 623 | * <li>{@link RequiredProperty}</li> | |
| 624 | * <li>{@link RequiredClasses}</li> | |
| 625 | * <li>{@link RequiredProperties}</li> | |
| 626 | * </ul> | |
| 627 | * Then if condition evaluation returns true, your implementation will be | |
| 628 | * used. If you provide several annotations, your implementation will be | |
| 629 | * used only if all conditions are met (and operator). | |
| 630 | * | |
| 631 | * <p> | |
| 632 | * If your custom implementation implements {@link ActivableAtRuntime}, and | |
| 633 | * the provided condition evaluation returns true, then your implementation | |
| 634 | * will be used. | |
| 635 | * | |
| 636 | * See {@link MessageConditions} to build your condition. | |
| 637 | * </p> | |
| 638 | * | |
| 639 | * <p> | |
| 640 | * If neither annotations nor implementation of {@link ActivableAtRuntime} | |
| 641 | * is used, then your custom implementation will be always used. All other | |
| 642 | * implementations (even standard ones) will never be used. | |
| 643 | * </p> | |
| 644 | * | |
| 645 | * @param sender | |
| 646 | * the sender to register | |
| 647 | * @return this instance for fluent chaining | |
| 648 | */ | |
| 649 | public EmailBuilder customSender(MessageSender sender) { | |
| 650 |
3
1. customSender : removed call to fr/sii/ogham/core/builder/sender/SenderImplementationBuilderHelper::customSender → NO_COVERAGE 2. customSender : removed call to fr/sii/ogham/core/builder/sender/SenderImplementationBuilderHelper::customSender → KILLED 3. customSender : removed call to fr/sii/ogham/core/builder/sender/SenderImplementationBuilderHelper::customSender → KILLED |
senderBuilderHelper.customSender(sender); |
| 651 |
3
1. customSender : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::customSender → NO_COVERAGE 2. customSender : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::customSender → KILLED 3. customSender : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::customSender → KILLED |
return this; |
| 652 | } | |
| 653 | ||
| 654 | /** | |
| 655 | * Registers and configures sender through a dedicated builder. | |
| 656 | * | |
| 657 | * For example: | |
| 658 | * | |
| 659 | * <pre> | |
| 660 | * .sender(JavaMailBuilder.class) | |
| 661 | * .host("localhost"); | |
| 662 | * </pre> | |
| 663 | * | |
| 664 | * <p> | |
| 665 | * If your custom builder is annotated by one or several of: | |
| 666 | * <ul> | |
| 667 | * <li>{@link RequiredClass}</li> | |
| 668 | * <li>{@link RequiredProperty}</li> | |
| 669 | * <li>{@link RequiredClasses}</li> | |
| 670 | * <li>{@link RequiredProperties}</li> | |
| 671 | * </ul> | |
| 672 | * Then if condition evaluation returns true, your built implementation will | |
| 673 | * be used. If you provide several annotations, your built implementation | |
| 674 | * will be used only if all conditions are met (and operator). | |
| 675 | * | |
| 676 | * <p> | |
| 677 | * If your custom builder implements {@link ActivableAtRuntime}, and the | |
| 678 | * provided condition evaluation returns true, then your built | |
| 679 | * implementation will be used. | |
| 680 | * | |
| 681 | * See {@link MessageConditions} to build your condition. | |
| 682 | * </p> | |
| 683 | * | |
| 684 | * <p> | |
| 685 | * If neither annotations nor implementation of {@link ActivableAtRuntime} | |
| 686 | * is used, then your built implementation will be always used. All other | |
| 687 | * implementations (even standard ones) will never be used. | |
| 688 | * </p> | |
| 689 | * | |
| 690 | * <p> | |
| 691 | * In order to be able to keep chaining, you builder instance may provide a | |
| 692 | * constructor with one argument with the type of the parent builder | |
| 693 | * ({@link EmailBuilder}). If you don't care about chaining, just provide a | |
| 694 | * default constructor. | |
| 695 | * </p> | |
| 696 | * | |
| 697 | * <p> | |
| 698 | * Your builder may return {@code null} when calling | |
| 699 | * {@link Builder#build()}. In this case it means that your implementation | |
| 700 | * can't be used due to current environment. Your implementation is then not | |
| 701 | * registered. | |
| 702 | * </p> | |
| 703 | * | |
| 704 | * @param builderClass | |
| 705 | * the builder class to instantiate | |
| 706 | * @param <T> | |
| 707 | * the type of the builder | |
| 708 | * @return the builder to configure the implementation | |
| 709 | * | |
| 710 | */ | |
| 711 | public <T extends Builder<? extends MessageSender>> T sender(Class<T> builderClass) { | |
| 712 |
6
1. sender : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::sender → NO_COVERAGE 2. sender : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::sender → KILLED 3. sender : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::sender → KILLED 4. sender : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::sender → KILLED 5. sender : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::sender → KILLED 6. sender : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::sender → KILLED |
return senderBuilderHelper.register(builderClass); |
| 713 | } | |
| 714 | ||
| 715 | /** | |
| 716 | * If a variant is missing, then force to fail. | |
| 717 | * | |
| 718 | * <p> | |
| 719 | * This may be useful if you want for example to always provide a text | |
| 720 | * fallback when using an html template. So if a client can't read the html | |
| 721 | * version, the fallback version will still always be readable. So to avoid | |
| 722 | * forgetting to write text template, set this to true. | |
| 723 | * </p> | |
| 724 | * | |
| 725 | * <p> | |
| 726 | * The value set using this method takes precedence over any property and | |
| 727 | * default value configured using {@link #failIfMissingVariant()}. | |
| 728 | * | |
| 729 | * <pre> | |
| 730 | * .failIfMissingVariant(false) | |
| 731 | * .failIfMissingVariant() | |
| 732 | * .properties("${custom.property.high-priority}", "${custom.property.low-priority}") | |
| 733 | * .defaultValue(true) | |
| 734 | * </pre> | |
| 735 | * | |
| 736 | * <pre> | |
| 737 | * .failIfMissingVariant(false) | |
| 738 | * .failIfMissingVariant() | |
| 739 | * .properties("${custom.property.high-priority}", "${custom.property.low-priority}") | |
| 740 | * .defaultValue(true) | |
| 741 | * </pre> | |
| 742 | * | |
| 743 | * In both cases, {@code failIfMissingVariant(false)} is used. | |
| 744 | * | |
| 745 | * <p> | |
| 746 | * If this method is called several times, only the last value is used. | |
| 747 | * | |
| 748 | * <p> | |
| 749 | * If {@code null} value is set, it is like not setting a value at all. The | |
| 750 | * property/default value configuration is applied. | |
| 751 | * | |
| 752 | * @param fail | |
| 753 | * fail if a variant is missing | |
| 754 | * @return this instance for fluent chaining | |
| 755 | */ | |
| 756 | public EmailBuilder failIfMissingVariant(Boolean fail) { | |
| 757 | templateBuilderHelper.failIfMissingVariant(fail); | |
| 758 |
1
1. failIfMissingVariant : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::failIfMissingVariant → NO_COVERAGE |
return this; |
| 759 | } | |
| 760 | ||
| 761 | /** | |
| 762 | * If a variant is missing, then force to fail. | |
| 763 | * | |
| 764 | * <p> | |
| 765 | * This may be useful if you want for example to always provide a text | |
| 766 | * fallback when using an html template. So if a client can't read the html | |
| 767 | * version, the fallback version will still always be readable. So to avoid | |
| 768 | * forgetting to write text template, set this to true. | |
| 769 | * </p> | |
| 770 | * | |
| 771 | * <p> | |
| 772 | * This method is mainly used by {@link Configurer}s to register some | |
| 773 | * property keys and/or a default value. The aim is to let developer be able | |
| 774 | * to externalize its configuration (using system properties, configuration | |
| 775 | * file or anything else). If the developer doesn't configure any value for | |
| 776 | * the registered properties, the default value is used (if set). | |
| 777 | * | |
| 778 | * <pre> | |
| 779 | * .failIfMissingVariant() | |
| 780 | * .properties("${custom.property.high-priority}", "${custom.property.low-priority}") | |
| 781 | * .defaultValue(true) | |
| 782 | * </pre> | |
| 783 | * | |
| 784 | * <p> | |
| 785 | * Non-null value set using {@link #failIfMissingVariant(Boolean)} takes | |
| 786 | * precedence over property values and default value. | |
| 787 | * | |
| 788 | * <pre> | |
| 789 | * .failIfMissingVariant(false) | |
| 790 | * .failIfMissingVariant() | |
| 791 | * .properties("${custom.property.high-priority}", "${custom.property.low-priority}") | |
| 792 | * .defaultValue(true) | |
| 793 | * </pre> | |
| 794 | * | |
| 795 | * The value {@code false} is used regardless of the value of the properties | |
| 796 | * and default value. | |
| 797 | * | |
| 798 | * <p> | |
| 799 | * See {@link ConfigurationValueBuilder} for more information. | |
| 800 | * | |
| 801 | * | |
| 802 | * @return the builder to configure property keys/default value | |
| 803 | */ | |
| 804 | public ConfigurationValueBuilder<EmailBuilder, Boolean> failIfMissingVariant() { | |
| 805 |
8
1. failIfMissingVariant : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::failIfMissingVariant → NO_COVERAGE 2. failIfMissingVariant : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::failIfMissingVariant → KILLED 3. failIfMissingVariant : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::failIfMissingVariant → KILLED 4. failIfMissingVariant : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::failIfMissingVariant → KILLED 5. failIfMissingVariant : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::failIfMissingVariant → KILLED 6. failIfMissingVariant : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::failIfMissingVariant → KILLED 7. failIfMissingVariant : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::failIfMissingVariant → KILLED 8. failIfMissingVariant : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::failIfMissingVariant → KILLED |
return new ConfigurationValueBuilderDelegate<>(this, templateBuilderHelper.failIfMissingVariant()); |
| 806 | } | |
| 807 | ||
| 808 | /** | |
| 809 | * When {@link #failIfMissingVariant()} is enabled, also indicate which | |
| 810 | * paths were tried in order to help debugging why a variant was not found. | |
| 811 | * | |
| 812 | * <p> | |
| 813 | * The value set using this method takes precedence over any property and | |
| 814 | * default value configured using {@link #listPossiblePaths()}. | |
| 815 | * | |
| 816 | * <pre> | |
| 817 | * .listPossiblePaths(true) | |
| 818 | * .listPossiblePaths() | |
| 819 | * .properties("${custom.property.high-priority}", "${custom.property.low-priority}") | |
| 820 | * .defaultValue(false) | |
| 821 | * </pre> | |
| 822 | * | |
| 823 | * <pre> | |
| 824 | * .listPossiblePaths(true) | |
| 825 | * .listPossiblePaths() | |
| 826 | * .properties("${custom.property.high-priority}", "${custom.property.low-priority}") | |
| 827 | * .defaultValue(false) | |
| 828 | * </pre> | |
| 829 | * | |
| 830 | * In both cases, {@code listPossiblePaths(true)} is used. | |
| 831 | * | |
| 832 | * <p> | |
| 833 | * If this method is called several times, only the last value is used. | |
| 834 | * | |
| 835 | * <p> | |
| 836 | * If {@code null} value is set, it is like not setting a value at all. The | |
| 837 | * property/default value configuration is applied. | |
| 838 | * | |
| 839 | * @param enable | |
| 840 | * enable/disable tracking of possible paths for template | |
| 841 | * variants | |
| 842 | * @return this instance for fluent chaining | |
| 843 | */ | |
| 844 | public EmailBuilder listPossiblePaths(Boolean enable) { | |
| 845 | templateBuilderHelper.listPossiblePaths(enable); | |
| 846 |
1
1. listPossiblePaths : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::listPossiblePaths → NO_COVERAGE |
return this; |
| 847 | } | |
| 848 | ||
| 849 | /** | |
| 850 | * When {@link #failIfMissingVariant()} is enabled, also indicate which | |
| 851 | * paths were tried in order to help debugging why a variant was not found. | |
| 852 | * | |
| 853 | * <p> | |
| 854 | * This method is mainly used by {@link Configurer}s to register some | |
| 855 | * property keys and/or a default value. The aim is to let developer be able | |
| 856 | * to externalize its configuration (using system properties, configuration | |
| 857 | * file or anything else). If the developer doesn't configure any value for | |
| 858 | * the registered properties, the default value is used (if set). | |
| 859 | * | |
| 860 | * <pre> | |
| 861 | * .listPossiblePaths() | |
| 862 | * .properties("${custom.property.high-priority}", "${custom.property.low-priority}") | |
| 863 | * .defaultValue(false) | |
| 864 | * </pre> | |
| 865 | * | |
| 866 | * <p> | |
| 867 | * Non-null value set using {@link #listPossiblePaths(Boolean)} takes | |
| 868 | * precedence over property values and default value. | |
| 869 | * | |
| 870 | * <pre> | |
| 871 | * .listPossiblePaths(true) | |
| 872 | * .listPossiblePaths() | |
| 873 | * .properties("${custom.property.high-priority}", "${custom.property.low-priority}") | |
| 874 | * .defaultValue(false) | |
| 875 | * </pre> | |
| 876 | * | |
| 877 | * The value {@code true} is used regardless of the value of the properties | |
| 878 | * and default value. | |
| 879 | * | |
| 880 | * <p> | |
| 881 | * See {@link ConfigurationValueBuilder} for more information. | |
| 882 | * | |
| 883 | * | |
| 884 | * @return the builder to configure property keys/default value | |
| 885 | */ | |
| 886 | public ConfigurationValueBuilder<EmailBuilder, Boolean> listPossiblePaths() { | |
| 887 |
8
1. listPossiblePaths : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::listPossiblePaths → NO_COVERAGE 2. listPossiblePaths : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::listPossiblePaths → KILLED 3. listPossiblePaths : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::listPossiblePaths → KILLED 4. listPossiblePaths : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::listPossiblePaths → KILLED 5. listPossiblePaths : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::listPossiblePaths → KILLED 6. listPossiblePaths : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::listPossiblePaths → KILLED 7. listPossiblePaths : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::listPossiblePaths → KILLED 8. listPossiblePaths : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::listPossiblePaths → KILLED |
return new ConfigurationValueBuilderDelegate<>(this, templateBuilderHelper.listPossiblePaths()); |
| 888 | } | |
| 889 | ||
| 890 | /** | |
| 891 | * Provide custom resolver that will handle a missing variant. | |
| 892 | * | |
| 893 | * @param resolver | |
| 894 | * the custom resolver | |
| 895 | * @return this instance for fluent chaining | |
| 896 | */ | |
| 897 | public EmailBuilder missingVariant(VariantResolver resolver) { | |
| 898 |
1
1. missingVariant : removed call to fr/sii/ogham/core/builder/template/TemplateBuilderHelper::missingVariant → NO_COVERAGE |
templateBuilderHelper.missingVariant(resolver); |
| 899 |
1
1. missingVariant : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::missingVariant → NO_COVERAGE |
return this; |
| 900 | } | |
| 901 | | |
| 902 | /** | |
| 903 | * Configure automatic retry if message couldn't be sent. | |
| 904 | * | |
| 905 | * | |
| 906 | * For example: | |
| 907 | * | |
| 908 | * <pre> | |
| 909 | * .autoRetry() | |
| 910 | * .fixedDelay() | |
| 911 | * .maxRetries().properties("${ogham.email.send-retry.max-attempts}").and() | |
| 912 | * .delay().properties("${ogham.email.send-retry.delay-between-attempts}") | |
| 913 | * </pre> | |
| 914 | * | |
| 915 | * | |
| 916 | * <p> | |
| 917 | * This builder lets you configure: | |
| 918 | * <ul> | |
| 919 | * <li>The retry strategy: | |
| 920 | * <ul> | |
| 921 | * <li>{@link FixedDelayRetry}: wait for a fixed delay after the last | |
| 922 | * failure</li> | |
| 923 | * <li>{@link FixedIntervalRetry}: wait for a fixed delay between executions | |
| 924 | * (do not wait for the end of the action)</li> | |
| 925 | * <li>{@link ExponentialDelayRetry}: start with a delay, the next delay | |
| 926 | * will be doubled on so on</li> | |
| 927 | * <li>{@link PerExecutionDelayRetry}: provide a custom delay for each | |
| 928 | * execution</li> | |
| 929 | * </ul> | |
| 930 | * </li> | |
| 931 | * <li>The {@link RetryExecutor} implementation</li> | |
| 932 | * <li>The {@link Awaiter} implementation</li> | |
| 933 | * <li>The {@link Condition} used to determine if the raised error should | |
| 934 | * trigger a retry or not</li> | |
| 935 | * </ul> | |
| 936 | * | |
| 937 | * @return the builder to configure retry management | |
| 938 | */ | |
| 939 | public RetryBuilder<EmailBuilder> autoRetry() { | |
| 940 |
8
1. autoRetry : negated conditional → NO_COVERAGE 2. autoRetry : negated conditional → KILLED 3. autoRetry : negated conditional → KILLED 4. autoRetry : negated conditional → KILLED 5. autoRetry : negated conditional → KILLED 6. autoRetry : negated conditional → KILLED 7. autoRetry : negated conditional → KILLED 8. autoRetry : negated conditional → KILLED |
if (retryBuilder == null) { |
| 941 | retryBuilder = new RetryBuilder<>(this, buildContext); | |
| 942 | } | |
| 943 |
8
1. autoRetry : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::autoRetry → NO_COVERAGE 2. autoRetry : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::autoRetry → KILLED 3. autoRetry : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::autoRetry → KILLED 4. autoRetry : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::autoRetry → KILLED 5. autoRetry : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::autoRetry → KILLED 6. autoRetry : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::autoRetry → KILLED 7. autoRetry : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::autoRetry → KILLED 8. autoRetry : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::autoRetry → KILLED |
return retryBuilder; |
| 944 | } | |
| 945 | ||
| 946 | @Override | |
| 947 | public ConditionalSender build() { | |
| 948 | EmailSender emailSender = buildContext.register(new EmailSender()); | |
| 949 | ConditionalSender sender = emailSender; | |
| 950 |
7
1. build : removed call to fr/sii/ogham/core/builder/sender/SenderImplementationBuilderHelper::addSenders → SURVIVED 2. build : removed call to fr/sii/ogham/core/builder/sender/SenderImplementationBuilderHelper::addSenders → NO_COVERAGE 3. build : removed call to fr/sii/ogham/core/builder/sender/SenderImplementationBuilderHelper::addSenders → KILLED 4. build : removed call to fr/sii/ogham/core/builder/sender/SenderImplementationBuilderHelper::addSenders → KILLED 5. build : removed call to fr/sii/ogham/core/builder/sender/SenderImplementationBuilderHelper::addSenders → KILLED 6. build : removed call to fr/sii/ogham/core/builder/sender/SenderImplementationBuilderHelper::addSenders → KILLED 7. build : removed call to fr/sii/ogham/core/builder/sender/SenderImplementationBuilderHelper::addSenders → KILLED |
senderBuilderHelper.addSenders(emailSender); |
| 951 |
4
1. build : negated conditional → NO_COVERAGE 2. build : negated conditional → SURVIVED 3. build : negated conditional → KILLED 4. build : negated conditional → KILLED |
if (autofillBuilder != null) { |
| 952 | MessageFiller messageFiller = autofillBuilder.build(); | |
| 953 | LOG.debug("Automatic filling of message enabled {}", messageFiller); | |
| 954 | sender = buildContext.register(new FillerSender(messageFiller, sender)); | |
| 955 | } | |
| 956 |
4
1. build : negated conditional → NO_COVERAGE 2. build : negated conditional → SURVIVED 3. build : negated conditional → KILLED 4. build : negated conditional → KILLED |
if (attachmentBuilder != null) { |
| 957 | AttachmentResourceTranslator resourceTranslator = attachmentBuilder.build(); | |
| 958 | LOG.debug("Resource translation enabled {}", resourceTranslator); | |
| 959 | sender = buildContext.register(new AttachmentResourceTranslatorSender(resourceTranslator, sender)); | |
| 960 | } | |
| 961 |
8
1. build : negated conditional → NO_COVERAGE 2. build : negated conditional → SURVIVED 3. build : negated conditional → NO_COVERAGE 4. build : negated conditional → SURVIVED 5. build : negated conditional → NO_COVERAGE 6. build : negated conditional → SURVIVED 7. build : negated conditional → KILLED 8. build : negated conditional → KILLED |
if (templateBuilderHelper.hasRegisteredTemplates() || cssBuilder != null || imageBuilder != null) { |
| 962 | ContentTranslator translator = buildContentTranslator(); | |
| 963 | LOG.debug("Content translation enabled {}", translator); | |
| 964 | sender = buildContext.register(new ContentTranslatorSender(translator, sender)); | |
| 965 | } | |
| 966 | RetryExecutor retryExecutor = BuilderUtils.build(retryBuilder); | |
| 967 |
7
1. build : negated conditional → NO_COVERAGE 2. build : negated conditional → SURVIVED 3. build : negated conditional → KILLED 4. build : negated conditional → KILLED 5. build : negated conditional → KILLED 6. build : negated conditional → KILLED 7. build : negated conditional → KILLED |
if (retryExecutor != null) { |
| 968 | LOG.debug("Automatic retry of message sending enabled {}", retryExecutor); | |
| 969 | sender = buildContext.register(new AutoRetrySender(sender, retryExecutor)); | |
| 970 | } | |
| 971 |
8
1. build : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::build → NO_COVERAGE 2. build : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::build → KILLED 3. build : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::build → KILLED 4. build : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::build → KILLED 5. build : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::build → KILLED 6. build : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::build → KILLED 7. build : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::build → KILLED 8. build : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::build → KILLED |
return sender; |
| 972 | } | |
| 973 | ||
| 974 | private ContentTranslator buildContentTranslator() { | |
| 975 | EveryContentTranslator translator = buildContext.register(new EveryContentTranslator()); | |
| 976 |
5
1. buildContentTranslator : removed call to fr/sii/ogham/email/builder/EmailBuilder::addTemplateTranslator → NO_COVERAGE 2. buildContentTranslator : removed call to fr/sii/ogham/email/builder/EmailBuilder::addTemplateTranslator → SURVIVED 3. buildContentTranslator : removed call to fr/sii/ogham/email/builder/EmailBuilder::addTemplateTranslator → KILLED 4. buildContentTranslator : removed call to fr/sii/ogham/email/builder/EmailBuilder::addTemplateTranslator → KILLED 5. buildContentTranslator : removed call to fr/sii/ogham/email/builder/EmailBuilder::addTemplateTranslator → KILLED |
addTemplateTranslator(translator); |
| 977 |
3
1. buildContentTranslator : removed call to fr/sii/ogham/email/builder/EmailBuilder::addMultiContent → NO_COVERAGE 2. buildContentTranslator : removed call to fr/sii/ogham/email/builder/EmailBuilder::addMultiContent → SURVIVED 3. buildContentTranslator : removed call to fr/sii/ogham/email/builder/EmailBuilder::addMultiContent → KILLED |
addMultiContent(translator); |
| 978 |
3
1. buildContentTranslator : removed call to fr/sii/ogham/email/builder/EmailBuilder::addCssInlining → SURVIVED 2. buildContentTranslator : removed call to fr/sii/ogham/email/builder/EmailBuilder::addCssInlining → NO_COVERAGE 3. buildContentTranslator : removed call to fr/sii/ogham/email/builder/EmailBuilder::addCssInlining → KILLED |
addCssInlining(translator); |
| 979 |
3
1. buildContentTranslator : removed call to fr/sii/ogham/email/builder/EmailBuilder::addImageInlining → SURVIVED 2. buildContentTranslator : removed call to fr/sii/ogham/email/builder/EmailBuilder::addImageInlining → NO_COVERAGE 3. buildContentTranslator : removed call to fr/sii/ogham/email/builder/EmailBuilder::addImageInlining → KILLED |
addImageInlining(translator); |
| 980 |
7
1. buildContentTranslator : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::buildContentTranslator → SURVIVED 2. buildContentTranslator : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::buildContentTranslator → NO_COVERAGE 3. buildContentTranslator : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::buildContentTranslator → KILLED 4. buildContentTranslator : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::buildContentTranslator → KILLED 5. buildContentTranslator : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::buildContentTranslator → KILLED 6. buildContentTranslator : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::buildContentTranslator → KILLED 7. buildContentTranslator : replaced return value with null for fr/sii/ogham/email/builder/EmailBuilder::buildContentTranslator → KILLED |
return translator; |
| 981 | } | |
| 982 | ||
| 983 | private void addTemplateTranslator(EveryContentTranslator translator) { | |
| 984 |
8
1. addTemplateTranslator : negated conditional → NO_COVERAGE 2. addTemplateTranslator : negated conditional → KILLED 3. addTemplateTranslator : negated conditional → KILLED 4. addTemplateTranslator : negated conditional → KILLED 5. addTemplateTranslator : negated conditional → KILLED 6. addTemplateTranslator : negated conditional → KILLED 7. addTemplateTranslator : negated conditional → KILLED 8. addTemplateTranslator : negated conditional → KILLED |
if (!templateBuilderHelper.hasRegisteredTemplates()) { |
| 985 | return; | |
| 986 | } | |
| 987 | TemplateParser templateParser = templateBuilderHelper.buildTemplateParser(); | |
| 988 | LOG.debug("Registering content translator that parses templates using {}", templateParser); | |
| 989 |
4
1. addTemplateTranslator : removed call to fr/sii/ogham/core/translator/content/EveryContentTranslator::addTranslator → NO_COVERAGE 2. addTemplateTranslator : removed call to fr/sii/ogham/core/translator/content/EveryContentTranslator::addTranslator → KILLED 3. addTemplateTranslator : removed call to fr/sii/ogham/core/translator/content/EveryContentTranslator::addTranslator → KILLED 4. addTemplateTranslator : removed call to fr/sii/ogham/core/translator/content/EveryContentTranslator::addTranslator → KILLED |
translator.addTranslator(buildContext.register(new TemplateContentTranslator(templateParser, templateBuilderHelper.buildVariant()))); |
| 990 | } | |
| 991 | ||
| 992 | private void addMultiContent(EveryContentTranslator translator) { | |
| 993 |
3
1. addMultiContent : removed call to fr/sii/ogham/core/translator/content/EveryContentTranslator::addTranslator → SURVIVED 2. addMultiContent : removed call to fr/sii/ogham/core/translator/content/EveryContentTranslator::addTranslator → NO_COVERAGE 3. addMultiContent : removed call to fr/sii/ogham/core/translator/content/EveryContentTranslator::addTranslator → KILLED |
translator.addTranslator(buildContext.register(new MultiContentTranslator(translator))); |
| 994 | } | |
| 995 | ||
| 996 | private void addImageInlining(EveryContentTranslator translator) { | |
| 997 |
3
1. addImageInlining : negated conditional → NO_COVERAGE 2. addImageInlining : negated conditional → SURVIVED 3. addImageInlining : negated conditional → KILLED |
if (imageBuilder == null) { |
| 998 | return; | |
| 999 | } | |
| 1000 | ContentTranslator imageInliner = imageBuilder.build(); | |
| 1001 |
3
1. addImageInlining : negated conditional → NO_COVERAGE 2. addImageInlining : negated conditional → SURVIVED 3. addImageInlining : negated conditional → KILLED |
if (imageInliner != null) { |
| 1002 | LOG.debug("Image inlining is enabled"); | |
| 1003 |
3
1. addImageInlining : removed call to fr/sii/ogham/core/translator/content/EveryContentTranslator::addTranslator → SURVIVED 2. addImageInlining : removed call to fr/sii/ogham/core/translator/content/EveryContentTranslator::addTranslator → NO_COVERAGE 3. addImageInlining : removed call to fr/sii/ogham/core/translator/content/EveryContentTranslator::addTranslator → KILLED |
translator.addTranslator(imageInliner); |
| 1004 | } | |
| 1005 | } | |
| 1006 | ||
| 1007 | private void addCssInlining(EveryContentTranslator translator) { | |
| 1008 |
3
1. addCssInlining : negated conditional → NO_COVERAGE 2. addCssInlining : negated conditional → SURVIVED 3. addCssInlining : negated conditional → KILLED |
if (cssBuilder == null) { |
| 1009 | return; | |
| 1010 | } | |
| 1011 | ContentTranslator cssInliner = cssBuilder.build(); | |
| 1012 |
3
1. addCssInlining : negated conditional → SURVIVED 2. addCssInlining : negated conditional → NO_COVERAGE 3. addCssInlining : negated conditional → KILLED |
if (cssInliner != null) { |
| 1013 | LOG.debug("CSS inlining is enabled"); | |
| 1014 |
3
1. addCssInlining : removed call to fr/sii/ogham/core/translator/content/EveryContentTranslator::addTranslator → SURVIVED 2. addCssInlining : removed call to fr/sii/ogham/core/translator/content/EveryContentTranslator::addTranslator → NO_COVERAGE 3. addCssInlining : removed call to fr/sii/ogham/core/translator/content/EveryContentTranslator::addTranslator → KILLED |
translator.addTranslator(cssInliner); |
| 1015 | } | |
| 1016 | } | |
| 1017 | ||
| 1018 | } | |
Mutations | ||
| 451 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 |
|
| 454 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 |
|
| 502 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 |
|
| 505 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 |
|
| 526 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 |
|
| 529 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 |
|
| 566 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 |
|
| 569 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 |
|
| 613 |
1.1 2.2 3.3 4.4 5.5 |
|
| 650 |
1.1 2.2 3.3 |
|
| 651 |
1.1 2.2 3.3 |
|
| 712 |
1.1 2.2 3.3 4.4 5.5 6.6 |
|
| 758 |
1.1 |
|
| 805 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 |
|
| 846 |
1.1 |
|
| 887 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 |
|
| 898 |
1.1 |
|
| 899 |
1.1 |
|
| 940 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 |
|
| 943 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 |
|
| 950 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 |
|
| 951 |
1.1 2.2 3.3 4.4 |
|
| 956 |
1.1 2.2 3.3 4.4 |
|
| 961 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 |
|
| 967 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 |
|
| 971 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 |
|
| 976 |
1.1 2.2 3.3 4.4 5.5 |
|
| 977 |
1.1 2.2 3.3 |
|
| 978 |
1.1 2.2 3.3 |
|
| 979 |
1.1 2.2 3.3 |
|
| 980 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 |
|
| 984 |
1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 |
|
| 989 |
1.1 2.2 3.3 4.4 |
|
| 993 |
1.1 2.2 3.3 |
|
| 997 |
1.1 2.2 3.3 |
|
| 1001 |
1.1 2.2 3.3 |
|
| 1003 |
1.1 2.2 3.3 |
|
| 1008 |
1.1 2.2 3.3 |
|
| 1012 |
1.1 2.2 3.3 |
|
| 1014 |
1.1 2.2 3.3 |