1 | package fr.sii.ogham.email.builder.javamail; | |
2 | ||
3 | import static fr.sii.ogham.core.condition.fluent.MessageConditions.requiredProperty; | |
4 | ||
5 | import java.io.InputStream; | |
6 | import java.nio.charset.Charset; | |
7 | import java.nio.file.Files; | |
8 | import java.util.Map; | |
9 | import java.util.Map.Entry; | |
10 | import java.util.Properties; | |
11 | import java.util.Set; | |
12 | import java.util.function.BiFunction; | |
13 | ||
14 | import javax.activation.MimetypesFileTypeMap; | |
15 | import javax.mail.Authenticator; | |
16 | import javax.mail.internet.MimeBodyPart; | |
17 | import javax.mail.internet.MimeMessage; | |
18 | import javax.mail.internet.MimeMultipart; | |
19 | ||
20 | import org.slf4j.Logger; | |
21 | import org.slf4j.LoggerFactory; | |
22 | ||
23 | import fr.sii.ogham.core.builder.ActivableAtRuntime; | |
24 | import fr.sii.ogham.core.builder.Builder; | |
25 | import fr.sii.ogham.core.builder.MessagingBuilder; | |
26 | import fr.sii.ogham.core.builder.configuration.ConfigurationValueBuilder; | |
27 | import fr.sii.ogham.core.builder.configuration.ConfigurationValueBuilderHelper; | |
28 | import fr.sii.ogham.core.builder.configurer.Configurer; | |
29 | import fr.sii.ogham.core.builder.context.BuildContext; | |
30 | import fr.sii.ogham.core.builder.context.DefaultBuildContext; | |
31 | import fr.sii.ogham.core.builder.env.EnvironmentBuilder; | |
32 | import fr.sii.ogham.core.builder.mimetype.MimetypeDetectionBuilder; | |
33 | import fr.sii.ogham.core.builder.mimetype.MimetypeDetectionBuilderDelegate; | |
34 | import fr.sii.ogham.core.builder.mimetype.SimpleMimetypeDetectionBuilder; | |
35 | import fr.sii.ogham.core.charset.CharsetDetector; | |
36 | import fr.sii.ogham.core.charset.FixedCharsetDetector; | |
37 | import fr.sii.ogham.core.condition.Condition; | |
38 | import fr.sii.ogham.core.convert.Converter; | |
39 | import fr.sii.ogham.core.env.FirstExistingPropertiesResolver; | |
40 | import fr.sii.ogham.core.env.JavaPropertiesResolver; | |
41 | import fr.sii.ogham.core.env.PropertiesBridge; | |
42 | import fr.sii.ogham.core.env.PropertyResolver; | |
43 | import fr.sii.ogham.core.fluent.AbstractParent; | |
44 | import fr.sii.ogham.core.message.Message; | |
45 | import fr.sii.ogham.core.message.content.MayHaveStringContent; | |
46 | import fr.sii.ogham.core.message.content.MultiContent; | |
47 | import fr.sii.ogham.core.mimetype.MimeTypeProvider; | |
48 | import fr.sii.ogham.core.resource.FileResource; | |
49 | import fr.sii.ogham.core.resource.LookupResource; | |
50 | import fr.sii.ogham.core.resource.NamedResource; | |
51 | import fr.sii.ogham.core.resource.OverrideNameWrapper; | |
52 | import fr.sii.ogham.email.attachment.Attachment; | |
53 | import fr.sii.ogham.email.builder.EmailBuilder; | |
54 | import fr.sii.ogham.email.exception.handler.AttachmentResourceHandlerException; | |
55 | import fr.sii.ogham.email.exception.handler.UnresolvableAttachmentResourceHandlerException; | |
56 | import fr.sii.ogham.email.message.Email; | |
57 | import fr.sii.ogham.email.message.content.ContentWithAttachments; | |
58 | import fr.sii.ogham.email.sender.impl.JavaMailSender; | |
59 | import fr.sii.ogham.email.sender.impl.javamail.ContentWithAttachmentsHandler; | |
60 | import fr.sii.ogham.email.sender.impl.javamail.FailResourceHandler; | |
61 | import fr.sii.ogham.email.sender.impl.javamail.FileResourceHandler; | |
62 | import fr.sii.ogham.email.sender.impl.javamail.JavaMailAttachmentHandler; | |
63 | import fr.sii.ogham.email.sender.impl.javamail.JavaMailInterceptor; | |
64 | import fr.sii.ogham.email.sender.impl.javamail.MapAttachmentResourceHandler; | |
65 | import fr.sii.ogham.email.sender.impl.javamail.MultiContentHandler; | |
66 | import fr.sii.ogham.email.sender.impl.javamail.OverrideNameWrapperResourceHandler; | |
67 | import fr.sii.ogham.email.sender.impl.javamail.PriorizedContentHandler; | |
68 | import fr.sii.ogham.email.sender.impl.javamail.StreamResourceHandler; | |
69 | import fr.sii.ogham.email.sender.impl.javamail.StringContentHandler; | |
70 | ||
71 | /** | |
72 | * Configures how Java Mail implementation will send {@link Email}s. | |
73 | * | |
74 | * <p> | |
75 | * To send {@link Email} using Java Mail, you need to register this builder into | |
76 | * a {@link MessagingBuilder} like this: | |
77 | * | |
78 | * <pre> | |
79 | * <code> | |
80 | * MessagingBuilder msgBuilder = ... | |
81 | * msgBuilder.email() | |
82 | * .sender(JavaMailBuilder.class) // registers the builder and accesses to that builder for configuring it | |
83 | * </code> | |
84 | * </pre> | |
85 | * | |
86 | * Once the builder is registered, sending email through Java Mail requires at | |
87 | * least host of the SMTP server. You can define it using: | |
88 | * | |
89 | * <pre> | |
90 | * <code> | |
91 | * msgBuilder.email() | |
92 | * .sender(JavaMailBuilder.class) // registers the builder and accesses to that builder for configuring it | |
93 | * .host("localhost") | |
94 | * </code> | |
95 | * </pre> | |
96 | * | |
97 | * Or you can also use property keys (using interpolation): | |
98 | * | |
99 | * <pre> | |
100 | * <code> | |
101 | * msgBuilder | |
102 | * .environment() | |
103 | * .properties() | |
104 | * .set("custom.property.for.host", "localhost") | |
105 | * .and() | |
106 | * .and() | |
107 | * .email() | |
108 | * .sender(JavaMailBuilder.class) // registers the builder and accesses to that builder for configuring it | |
109 | * .host() | |
110 | * .properties("${custom.property.for.host}") | |
111 | * </code> | |
112 | * </pre> | |
113 | * | |
114 | * You can do the same with port of the SMTP server. | |
115 | * | |
116 | * | |
117 | * <p> | |
118 | * SMTP server may require authentication. In most cases, authentication is done | |
119 | * using username/password. You can use this builder to quickly provide your | |
120 | * username and password: | |
121 | * | |
122 | * <pre> | |
123 | * <code> | |
124 | * .sender(JavaMailBuilder.class) | |
125 | * .authenticator() | |
126 | * .username("foo") | |
127 | * .password("bar") | |
128 | * </code> | |
129 | * </pre> | |
130 | * | |
131 | * If you need another authentication mechanism, you can directly provide your | |
132 | * own {@link Authenticator} implementation: | |
133 | * | |
134 | * <pre> | |
135 | * <code> | |
136 | * .sender(JavaMailBuilder.class) | |
137 | * .authenticator(new MyCustomAuthenticator()) | |
138 | * </code> | |
139 | * </pre> | |
140 | * | |
141 | * | |
142 | * <p> | |
143 | * Finally, Ogham will transform general {@link Email} object into | |
144 | * {@link MimeMessage}, {@link MimeMultipart}, {@link MimeBodyPart} objects. | |
145 | * This transformation will fit almost all use cases but you may need to | |
146 | * customize a part of the javax.mail message. Instead of doing again the same | |
147 | * work Ogham does, this builder allows you to intercept the message to modify | |
148 | * it just before sending it: | |
149 | * | |
150 | * <pre> | |
151 | * <code> | |
152 | * .sender(JavaMailBuilder.class) | |
153 | * .intercept(new MyCustomInterceptor()) | |
154 | * </code> | |
155 | * </pre> | |
156 | * | |
157 | * See {@link JavaMailInterceptor} for more information. | |
158 | * | |
159 | * | |
160 | * @author Aurélien Baudet | |
161 | * | |
162 | */ | |
163 | public class JavaMailBuilder extends AbstractParent<EmailBuilder> implements Builder<JavaMailSender>, ActivableAtRuntime { | |
164 | private static final Logger LOG = LoggerFactory.getLogger(JavaMailBuilder.class); | |
165 | ||
166 | private final BuildContext buildContext; | |
167 | private final ConfigurationValueBuilderHelper<JavaMailBuilder, String> hostValueBuilder; | |
168 | private final ConfigurationValueBuilderHelper<JavaMailBuilder, Integer> portValueBuilder; | |
169 | private final ConfigurationValueBuilderHelper<JavaMailBuilder, Charset> charsetValueBuilder; | |
170 | private final Properties additionalProperties; | |
171 | private Authenticator authenticator; | |
172 | private UsernamePasswordAuthenticatorBuilder authenticatorBuilder; | |
173 | private JavaMailInterceptor interceptor; | |
174 | private MimetypeDetectionBuilder<JavaMailBuilder> mimetypeBuilder; | |
175 | private CharsetDetector charsetDetector; | |
176 | ||
177 | /** | |
178 | * Default constructor when using JavaMail sender without all Ogham work. | |
179 | * | |
180 | * <strong>WARNING: use is only if you know what you are doing !</strong> | |
181 | */ | |
182 | public JavaMailBuilder() { | |
183 | this(null, new DefaultBuildContext()); | |
184 | mimetype(); | |
185 | } | |
186 | ||
187 | /** | |
188 | * Constructor that is called when using Ogham builder: | |
189 | * | |
190 | * <pre> | |
191 | * MessagingBuilder msgBuilder = ... | |
192 | * msgBuilder | |
193 | * .email() | |
194 | * .sender(JavaMailBuilder.class) | |
195 | * </pre> | |
196 | * | |
197 | * <p> | |
198 | * Initializes the builder with the parent instance (used by the | |
199 | * {@link #and()} method) and the {@link EnvironmentBuilder}. The | |
200 | * {@link EnvironmentBuilder} is used to evaluate property values when | |
201 | * {@link #build()} is called. | |
202 | * | |
203 | * @param parent | |
204 | * the parent builder instance for fluent chaining | |
205 | * @param buildContext | |
206 | * used to evaluate property values | |
207 | */ | |
208 | public JavaMailBuilder(EmailBuilder parent, BuildContext buildContext) { | |
209 | super(parent); | |
210 | this.buildContext = buildContext; | |
211 | hostValueBuilder = buildContext.newConfigurationValueBuilder(this, String.class); | |
212 | portValueBuilder = buildContext.newConfigurationValueBuilder(this, Integer.class); | |
213 | charsetValueBuilder = buildContext.newConfigurationValueBuilder(this, Charset.class); | |
214 | additionalProperties = new Properties(); | |
215 | } | |
216 | ||
217 | /** | |
218 | * Set the mail server address host (IP or hostname). | |
219 | * | |
220 | * <p> | |
221 | * The value set using this method takes precedence over any property and | |
222 | * default value configured using {@link #host()}. | |
223 | * | |
224 | * <pre> | |
225 | * .host("smtp.gmail.com") | |
226 | * .host() | |
227 | * .properties("${custom.property.high-priority}", "${custom.property.low-priority}") | |
228 | * .defaultValue("localhost") | |
229 | * </pre> | |
230 | * | |
231 | * <pre> | |
232 | * .host("smtp.gmail.com") | |
233 | * .host() | |
234 | * .properties("${custom.property.high-priority}", "${custom.property.low-priority}") | |
235 | * .defaultValue("localhost") | |
236 | * </pre> | |
237 | * | |
238 | * In both cases, {@code host("smtp.gmail.com")} is used. | |
239 | * | |
240 | * <p> | |
241 | * If this method is called several times, only the last value is used. | |
242 | * | |
243 | * <p> | |
244 | * If {@code null} value is set, it is like not setting a value at all. The | |
245 | * property/default value configuration is applied. | |
246 | * | |
247 | * @param host | |
248 | * the host of the mail server | |
249 | * @return this instance for fluent chaining | |
250 | */ | |
251 | public JavaMailBuilder host(String host) { | |
252 |
3
1. host : removed call to fr/sii/ogham/core/builder/configuration/ConfigurationValueBuilderHelper::setValue → NO_COVERAGE 2. host : removed call to fr/sii/ogham/core/builder/configuration/ConfigurationValueBuilderHelper::setValue → KILLED 3. host : removed call to fr/sii/ogham/core/builder/configuration/ConfigurationValueBuilderHelper::setValue → KILLED |
hostValueBuilder.setValue(host); |
253 |
3
1. host : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::host → NO_COVERAGE 2. host : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::host → SURVIVED 3. host : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::host → KILLED |
return this; |
254 | } | |
255 | ||
256 | /** | |
257 | * Set the mail server address host (IP or hostname). | |
258 | * | |
259 | * <p> | |
260 | * This method is mainly used by {@link Configurer}s to register some | |
261 | * property keys and/or a default value. The aim is to let developer be able | |
262 | * to externalize its configuration (using system properties, configuration | |
263 | * file or anything else). If the developer doesn't configure any value for | |
264 | * the registered properties, the default value is used (if set). | |
265 | * | |
266 | * <pre> | |
267 | * .host() | |
268 | * .properties("${custom.property.high-priority}", "${custom.property.low-priority}") | |
269 | * .defaultValue("localhost") | |
270 | * </pre> | |
271 | * | |
272 | * <p> | |
273 | * Non-null value set using {@link #host(String)} takes precedence over | |
274 | * property values and default value. | |
275 | * | |
276 | * <pre> | |
277 | * .host("smtp.gmail.com") | |
278 | * .host() | |
279 | * .properties("${custom.property.high-priority}", "${custom.property.low-priority}") | |
280 | * .defaultValue("localhost") | |
281 | * </pre> | |
282 | * | |
283 | * The value {@code "smtp.gmail.com"} is used regardless of the value of the | |
284 | * properties and default value. | |
285 | * | |
286 | * <p> | |
287 | * See {@link ConfigurationValueBuilder} for more information. | |
288 | * | |
289 | * | |
290 | * @return the builder to configure property keys/default value | |
291 | */ | |
292 | public ConfigurationValueBuilder<JavaMailBuilder, String> host() { | |
293 |
4
1. host : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::host → KILLED 2. host : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::host → KILLED 3. host : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::host → KILLED 4. host : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::host → KILLED |
return hostValueBuilder; |
294 | } | |
295 | ||
296 | /** | |
297 | * Set the mail server port. | |
298 | * | |
299 | * <p> | |
300 | * The value set using this method takes precedence over any property and | |
301 | * default value configured using {@link #port()}. | |
302 | * | |
303 | * <pre> | |
304 | * .port(10025) | |
305 | * .port() | |
306 | * .properties("${custom.property.high-priority}", "${custom.property.low-priority}") | |
307 | * .defaultValue(25) | |
308 | * </pre> | |
309 | * | |
310 | * <pre> | |
311 | * .port(10025) | |
312 | * .port() | |
313 | * .properties("${custom.property.high-priority}", "${custom.property.low-priority}") | |
314 | * .defaultValue(25) | |
315 | * </pre> | |
316 | * | |
317 | * In both cases, {@code port(10025)} is used. | |
318 | * | |
319 | * <p> | |
320 | * If this method is called several times, only the last value is used. | |
321 | * | |
322 | * <p> | |
323 | * If {@code null} value is set, it is like not setting a value at all. The | |
324 | * property/default value configuration is applied. | |
325 | * | |
326 | * @param port | |
327 | * the port of mail server | |
328 | * @return this instance for fluent chaining | |
329 | */ | |
330 | public JavaMailBuilder port(Integer port) { | |
331 |
2
1. port : removed call to fr/sii/ogham/core/builder/configuration/ConfigurationValueBuilderHelper::setValue → NO_COVERAGE 2. port : removed call to fr/sii/ogham/core/builder/configuration/ConfigurationValueBuilderHelper::setValue → KILLED |
portValueBuilder.setValue(port); |
332 |
2
1. port : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::port → NO_COVERAGE 2. port : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::port → KILLED |
return this; |
333 | } | |
334 | ||
335 | /** | |
336 | * Set the mail server port | |
337 | * | |
338 | * <p> | |
339 | * This method is mainly used by {@link Configurer}s to register some | |
340 | * property keys and/or a default value. The aim is to let developer be able | |
341 | * to externalize its configuration (using system properties, configuration | |
342 | * file or anything else). If the developer doesn't configure any value for | |
343 | * the registered properties, the default value is used (if set). | |
344 | * | |
345 | * <pre> | |
346 | * .port() | |
347 | * .properties("${custom.property.high-priority}", "${custom.property.low-priority}") | |
348 | * .defaultValue(25) | |
349 | * </pre> | |
350 | * | |
351 | * <p> | |
352 | * Non-null value set using {@link #port(Integer)} takes precedence over | |
353 | * property values and default value. | |
354 | * | |
355 | * <pre> | |
356 | * .port(10025) | |
357 | * .port() | |
358 | * .properties("${custom.property.high-priority}", "${custom.property.low-priority}") | |
359 | * .defaultValue(25) | |
360 | * </pre> | |
361 | * | |
362 | * The value {@code 10025} is used regardless of the value of the properties | |
363 | * and default value. | |
364 | * | |
365 | * <p> | |
366 | * See {@link ConfigurationValueBuilder} for more information. | |
367 | * | |
368 | * | |
369 | * @return the builder to configure property keys/default value | |
370 | */ | |
371 | public ConfigurationValueBuilder<JavaMailBuilder, Integer> port() { | |
372 |
4
1. port : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::port → KILLED 2. port : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::port → KILLED 3. port : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::port → KILLED 4. port : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::port → KILLED |
return portValueBuilder; |
373 | } | |
374 | ||
375 | /** | |
376 | * Set charset to use for email body. | |
377 | * | |
378 | * <p> | |
379 | * The value set using this method takes precedence over any property and | |
380 | * default value configured using {@link #charset()}. | |
381 | * | |
382 | * <pre> | |
383 | * .charset(StandardCharsets.UTF_16) | |
384 | * .charset() | |
385 | * .properties("${custom.property.high-priority}", "${custom.property.low-priority}") | |
386 | * .defaultValue(StandardCharsets.UTF_8) | |
387 | * </pre> | |
388 | * | |
389 | * <pre> | |
390 | * .charset(StandardCharsets.UTF_16) | |
391 | * .charset() | |
392 | * .properties("${custom.property.high-priority}", "${custom.property.low-priority}") | |
393 | * .defaultValue(StandardCharsets.UTF_8) | |
394 | * </pre> | |
395 | * | |
396 | * In both cases, {@code charset(StandardCharsets.UTF_16)} is used. | |
397 | * | |
398 | * <p> | |
399 | * If this method is called several times, only the last value is used. | |
400 | * | |
401 | * <p> | |
402 | * If {@code null} value is set, it is like not setting a value at all. The | |
403 | * property/default value configuration is applied. | |
404 | * | |
405 | * @param charset | |
406 | * the charset to use for email body | |
407 | * @return this instance for fluent chaining | |
408 | */ | |
409 | public JavaMailBuilder charset(Charset charset) { | |
410 |
1
1. charset : removed call to fr/sii/ogham/core/builder/configuration/ConfigurationValueBuilderHelper::setValue → NO_COVERAGE |
charsetValueBuilder.setValue(charset); |
411 |
1
1. charset : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::charset → NO_COVERAGE |
return this; |
412 | } | |
413 | ||
414 | /** | |
415 | * Set charset to use for email body | |
416 | * | |
417 | * <p> | |
418 | * This method is mainly used by {@link Configurer}s to register some | |
419 | * property keys and/or a default value. The aim is to let developer be able | |
420 | * to externalize its configuration (using system properties, configuration | |
421 | * file or anything else). If the developer doesn't configure any value for | |
422 | * the registered properties, the default value is used (if set). | |
423 | * | |
424 | * <pre> | |
425 | * .charset() | |
426 | * .properties("${custom.property.high-priority}", "${custom.property.low-priority}") | |
427 | * .defaultValue(StandardCharsets.UTF_8) | |
428 | * </pre> | |
429 | * | |
430 | * <p> | |
431 | * Non-null value set using {@link #charset(Charset)} takes precedence over | |
432 | * property values and default value. | |
433 | * | |
434 | * <pre> | |
435 | * .charset(StandardCharsets.UTF_16) | |
436 | * .charset() | |
437 | * .properties("${custom.property.high-priority}", "${custom.property.low-priority}") | |
438 | * .defaultValue(StandardCharsets.UTF_8) | |
439 | * </pre> | |
440 | * | |
441 | * The value {@code StandardCharsets.UTF_16} is used regardless of the value | |
442 | * of the properties and default value. | |
443 | * | |
444 | * <p> | |
445 | * See {@link ConfigurationValueBuilder} for more information. | |
446 | * | |
447 | * | |
448 | * @return the builder to configure property keys/default value | |
449 | */ | |
450 | public ConfigurationValueBuilder<JavaMailBuilder, Charset> charset() { | |
451 |
4
1. charset : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::charset → KILLED 2. charset : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::charset → KILLED 3. charset : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::charset → KILLED 4. charset : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::charset → KILLED |
return charsetValueBuilder; |
452 | } | |
453 | ||
454 | /** | |
455 | * Defines a custom detector that will indicate which charset corresponds | |
456 | * for a particular string. | |
457 | * | |
458 | * This value preempts any other value defined by calling | |
459 | * {@link #charset(Charset)} method. | |
460 | * | |
461 | * If this method is called several times, only the last provider is used. | |
462 | * | |
463 | * @param charsetDetector | |
464 | * the provider used to detect charset of a string | |
465 | * @return this instance for fluent chaining | |
466 | */ | |
467 | public JavaMailBuilder charset(CharsetDetector charsetDetector) { | |
468 | this.charsetDetector = charsetDetector; | |
469 |
1
1. charset : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::charset → NO_COVERAGE |
return this; |
470 | } | |
471 | ||
472 | /** | |
473 | * SMTP server may require authentication. In most cases, authentication is | |
474 | * done using username/password. You can use this builder to quickly provide | |
475 | * your username and password: | |
476 | * | |
477 | * <pre> | |
478 | * .sender(JavaMailBuilder.class) | |
479 | * .authenticator() | |
480 | * .username("foo") | |
481 | * .password("bar") | |
482 | * </pre> | |
483 | * | |
484 | * @return the builder to configure username/password authentication | |
485 | */ | |
486 | public UsernamePasswordAuthenticatorBuilder authenticator() { | |
487 |
4
1. authenticator : negated conditional → KILLED 2. authenticator : negated conditional → KILLED 3. authenticator : negated conditional → KILLED 4. authenticator : negated conditional → KILLED |
if (authenticatorBuilder == null) { |
488 | authenticatorBuilder = new UsernamePasswordAuthenticatorBuilder(this, buildContext); | |
489 | } | |
490 |
4
1. authenticator : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::authenticator → KILLED 2. authenticator : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::authenticator → KILLED 3. authenticator : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::authenticator → KILLED 4. authenticator : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::authenticator → KILLED |
return authenticatorBuilder; |
491 | } | |
492 | ||
493 | /** | |
494 | * SMTP server may require authentication. In most cases, authentication is | |
495 | * done using username/password. However, if you need another authentication | |
496 | * mechanism, you can directly provide your own {@link Authenticator} | |
497 | * implementation: | |
498 | * | |
499 | * <pre> | |
500 | * .sender(JavaMailBuilder.class) | |
501 | * .authenticator(new MyCustomAuthenticator()) | |
502 | * </pre> | |
503 | * | |
504 | * @param authenticator | |
505 | * the custom authenticator implementation | |
506 | * @return the builder to configure username/password authentication | |
507 | */ | |
508 | public JavaMailBuilder authenticator(Authenticator authenticator) { | |
509 | this.authenticator = authenticator; | |
510 |
1
1. authenticator : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::authenticator → NO_COVERAGE |
return this; |
511 | } | |
512 | ||
513 | /** | |
514 | * Ogham will transform general {@link Email} object into | |
515 | * {@link MimeMessage}, {@link MimeMultipart}, {@link MimeBodyPart} objects. | |
516 | * This transformation will fit almost all use cases but you may need to | |
517 | * customize a part of the javax.mail message. Instead of doing again the | |
518 | * same work Ogham does, this builder allows you to intercept the message to | |
519 | * modify it just before sending it: | |
520 | * | |
521 | * <pre> | |
522 | * .sender(JavaMailBuilder.class) | |
523 | * .intercept(new MyCustomInterceptor()) | |
524 | * </pre> | |
525 | * | |
526 | * See {@link JavaMailInterceptor} for more information. | |
527 | * | |
528 | * @param interceptor | |
529 | * the custom interceptor used to modify {@link MimeMessage} | |
530 | * @return this instance for fluent chaining | |
531 | */ | |
532 | public JavaMailBuilder intercept(JavaMailInterceptor interceptor) { | |
533 | this.interceptor = interceptor; | |
534 |
1
1. intercept : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::intercept → NO_COVERAGE |
return this; |
535 | } | |
536 | ||
537 | /** | |
538 | * Builder that configures mimetype detection. Detection is used here to | |
539 | * detect mimetype of {@link Attachment}s. | |
540 | * | |
541 | * There exists several implementations to provide the mimetype: | |
542 | * <ul> | |
543 | * <li>Using Java {@link MimetypesFileTypeMap}</li> | |
544 | * <li>Using Java 7 {@link Files#probeContentType(java.nio.file.Path)}</li> | |
545 | * <li>Using <a href="http://tika.apache.org/">Apache Tika</a></li> | |
546 | * <li>Using | |
547 | * <a href="https://github.com/arimus/jmimemagic">JMimeMagic</a></li> | |
548 | * </ul> | |
549 | * | |
550 | * <p> | |
551 | * Both implementations provided by Java are based on file extensions. This | |
552 | * can't be used in most cases as we often handle {@link InputStream}s. | |
553 | * </p> | |
554 | * | |
555 | * <p> | |
556 | * In previous version of Ogham, JMimeMagic was used and was working quite | |
557 | * well. Unfortunately, the library is no more maintained. | |
558 | * </p> | |
559 | * | |
560 | * <p> | |
561 | * You can configure how Tika will detect mimetype: | |
562 | * | |
563 | * <pre> | |
564 | * .mimetype() | |
565 | * .tika() | |
566 | * ... | |
567 | * </pre> | |
568 | * | |
569 | * <p> | |
570 | * This builder allows to use several providers. It will chain them until | |
571 | * one can find a valid mimetype. If none is found, you can explicitly | |
572 | * provide the default one: | |
573 | * | |
574 | * <pre> | |
575 | * .mimetype() | |
576 | * .defaultMimetype("text/html") | |
577 | * </pre> | |
578 | * | |
579 | * <p> | |
580 | * If no mimetype detector was previously defined, it creates a new one. | |
581 | * Then each time you call {@link #mimetype()}, the same instance is used. | |
582 | * </p> | |
583 | * | |
584 | * @return the builder to configure mimetype detection | |
585 | */ | |
586 | public MimetypeDetectionBuilder<JavaMailBuilder> mimetype() { | |
587 |
4
1. mimetype : negated conditional → KILLED 2. mimetype : negated conditional → KILLED 3. mimetype : negated conditional → KILLED 4. mimetype : negated conditional → KILLED |
if (mimetypeBuilder == null) { |
588 | mimetypeBuilder = new SimpleMimetypeDetectionBuilder<>(this, buildContext); | |
589 | } | |
590 |
4
1. mimetype : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::mimetype → KILLED 2. mimetype : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::mimetype → KILLED 3. mimetype : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::mimetype → KILLED 4. mimetype : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::mimetype → KILLED |
return mimetypeBuilder; |
591 | } | |
592 | ||
593 | /** | |
594 | * NOTE: this is mostly for advance usage (when creating a custom module). | |
595 | * | |
596 | * Inherits mimetype configuration from another builder. This is useful for | |
597 | * configuring independently different parts of Ogham but keeping a whole | |
598 | * coherence. | |
599 | * | |
600 | * The same instance is shared meaning that all changes done here will also | |
601 | * impact the other builder. | |
602 | * | |
603 | * <p> | |
604 | * If a previous builder was defined (by calling {@link #mimetype()} for | |
605 | * example), the new builder will override it. | |
606 | * | |
607 | * @param builder | |
608 | * the builder to inherit | |
609 | * @return this instance for fluent chaining | |
610 | */ | |
611 | public JavaMailBuilder mimetype(MimetypeDetectionBuilder<?> builder) { | |
612 | mimetypeBuilder = new MimetypeDetectionBuilderDelegate<>(this, builder); | |
613 |
1
1. mimetype : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::mimetype → NO_COVERAGE |
return this; |
614 | } | |
615 | ||
616 | /** | |
617 | * Register additional properties that are used by JavaMail session. | |
618 | * | |
619 | * <p> | |
620 | * If a key was previously registered, it is replaced by the new value. | |
621 | * | |
622 | * <p> | |
623 | * If the value is {@code null}, the key is removed. | |
624 | * | |
625 | * @param props | |
626 | * the properties to register | |
627 | * @return this instance for fluent chaining | |
628 | */ | |
629 | public JavaMailBuilder properties(Properties props) { | |
630 |
1
1. properties : removed call to fr/sii/ogham/email/builder/javamail/JavaMailBuilder::updateProperties → NO_COVERAGE |
updateProperties(props.entrySet()); |
631 |
1
1. properties : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::properties → NO_COVERAGE |
return this; |
632 | } | |
633 | ||
634 | /** | |
635 | * Register additional properties that are used by JavaMail session. | |
636 | * | |
637 | * <p> | |
638 | * If a key was previously registered, it is replaced by the new value. | |
639 | * | |
640 | * <p> | |
641 | * If the value is {@code null}, the key is removed. | |
642 | * | |
643 | * | |
644 | * @param props | |
645 | * the properties to register | |
646 | * @return this instance for fluent chaining | |
647 | */ | |
648 | public JavaMailBuilder properties(Map<String, String> props) { | |
649 |
2
1. properties : removed call to fr/sii/ogham/email/builder/javamail/JavaMailBuilder::updateProperties → NO_COVERAGE 2. properties : removed call to fr/sii/ogham/email/builder/javamail/JavaMailBuilder::updateProperties → SURVIVED |
updateProperties(props.entrySet()); |
650 |
2
1. properties : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::properties → SURVIVED 2. properties : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::properties → NO_COVERAGE |
return this; |
651 | } | |
652 | ||
653 | @Override | |
654 | public JavaMailSender build() { | |
655 | Properties props = buildProperties(); | |
656 | MimeTypeProvider mimetypeProvider = mimetype().build(); | |
657 | LOG.info("Sending email using JavaMail API is registered"); | |
658 | LOG.debug("SMTP server address: {}:{}", props.getProperty("mail.host"), props.getProperty("mail.port")); | |
659 | JavaMailAttachmentHandler attachmentHandler = buildAttachmentHandler(mimetypeProvider); | |
660 |
4
1. build : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::build → KILLED 2. build : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::build → KILLED 3. build : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::build → KILLED 4. build : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::build → KILLED |
return buildContext.register(new JavaMailSender(props, buildContentHandler(mimetypeProvider, attachmentHandler), attachmentHandler, buildAuthenticator(), interceptor)); |
661 | } | |
662 | ||
663 | @Override | |
664 | public Condition<Message> getCondition() { | |
665 | PropertyResolver propertyResolver = buildPropertyResolver(); | |
666 |
4
1. getCondition : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::getCondition → KILLED 2. getCondition : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::getCondition → KILLED 3. getCondition : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::getCondition → KILLED 4. getCondition : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::getCondition → KILLED |
return requiredProperty(propertyResolver, "mail.host").or(requiredProperty(propertyResolver, "mail.smtp.host")); |
667 | } | |
668 | ||
669 | private Properties buildProperties() { | |
670 |
4
1. buildProperties : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::buildProperties → TIMED_OUT 2. buildProperties : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::buildProperties → KILLED 3. buildProperties : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::buildProperties → KILLED 4. buildProperties : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::buildProperties → KILLED |
return buildContext.register(new PropertiesBridge(new FirstExistingPropertiesResolver(buildPropertyResolver(), new JavaPropertiesResolver(additionalProperties, getConverter())))); |
671 | } | |
672 | ||
673 | private OverrideJavaMailResolver buildPropertyResolver() { | |
674 |
4
1. buildPropertyResolver : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::buildPropertyResolver → KILLED 2. buildPropertyResolver : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::buildPropertyResolver → KILLED 3. buildPropertyResolver : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::buildPropertyResolver → KILLED 4. buildPropertyResolver : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::buildPropertyResolver → KILLED |
return buildContext.register(new OverrideJavaMailResolver(getPropertyResolver(), getConverter(), hostValueBuilder, portValueBuilder)); |
675 | } | |
676 | ||
677 | private Converter getConverter() { | |
678 |
4
1. getConverter : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::getConverter → KILLED 2. getConverter : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::getConverter → KILLED 3. getConverter : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::getConverter → KILLED 4. getConverter : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::getConverter → KILLED |
return buildContext.getConverter(); |
679 | } | |
680 | ||
681 | private Authenticator buildAuthenticator() { | |
682 |
2
1. buildAuthenticator : negated conditional → SURVIVED 2. buildAuthenticator : negated conditional → KILLED |
if (this.authenticator != null) { |
683 |
1
1. buildAuthenticator : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::buildAuthenticator → NO_COVERAGE |
return this.authenticator; |
684 | } | |
685 |
3
1. buildAuthenticator : negated conditional → SURVIVED 2. buildAuthenticator : negated conditional → KILLED 3. buildAuthenticator : negated conditional → KILLED |
if (authenticatorBuilder != null) { |
686 |
2
1. buildAuthenticator : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::buildAuthenticator → SURVIVED 2. buildAuthenticator : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::buildAuthenticator → KILLED |
return authenticatorBuilder.build(); |
687 | } | |
688 | return null; | |
689 | } | |
690 | ||
691 | private PriorizedContentHandler buildContentHandler(MimeTypeProvider mimetypeProvider, JavaMailAttachmentHandler attachmentHandler) { | |
692 | PriorizedContentHandler contentHandler = buildContext.register(new PriorizedContentHandler()); | |
693 |
3
1. buildContentHandler : removed call to fr/sii/ogham/email/sender/impl/javamail/PriorizedContentHandler::register → SURVIVED 2. buildContentHandler : removed call to fr/sii/ogham/email/sender/impl/javamail/PriorizedContentHandler::register → KILLED 3. buildContentHandler : removed call to fr/sii/ogham/email/sender/impl/javamail/PriorizedContentHandler::register → KILLED |
contentHandler.register(MultiContent.class, buildContext.register(new MultiContentHandler(contentHandler))); |
694 |
2
1. buildContentHandler : removed call to fr/sii/ogham/email/sender/impl/javamail/PriorizedContentHandler::register → SURVIVED 2. buildContentHandler : removed call to fr/sii/ogham/email/sender/impl/javamail/PriorizedContentHandler::register → KILLED |
contentHandler.register(ContentWithAttachments.class, buildContext.register(new ContentWithAttachmentsHandler(contentHandler, attachmentHandler))); |
695 |
4
1. buildContentHandler : removed call to fr/sii/ogham/email/sender/impl/javamail/PriorizedContentHandler::register → KILLED 2. buildContentHandler : removed call to fr/sii/ogham/email/sender/impl/javamail/PriorizedContentHandler::register → KILLED 3. buildContentHandler : removed call to fr/sii/ogham/email/sender/impl/javamail/PriorizedContentHandler::register → KILLED 4. buildContentHandler : removed call to fr/sii/ogham/email/sender/impl/javamail/PriorizedContentHandler::register → KILLED |
contentHandler.register(MayHaveStringContent.class, buildContext.register(new StringContentHandler(mimetypeProvider, buildCharset()))); |
696 |
4
1. buildContentHandler : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::buildContentHandler → KILLED 2. buildContentHandler : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::buildContentHandler → KILLED 3. buildContentHandler : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::buildContentHandler → KILLED 4. buildContentHandler : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::buildContentHandler → KILLED |
return contentHandler; |
697 | } | |
698 | ||
699 | private CharsetDetector buildCharset() { | |
700 |
4
1. buildCharset : negated conditional → KILLED 2. buildCharset : negated conditional → KILLED 3. buildCharset : negated conditional → KILLED 4. buildCharset : negated conditional → KILLED |
if (this.charsetDetector != null) { |
701 |
1
1. buildCharset : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::buildCharset → NO_COVERAGE |
return this.charsetDetector; |
702 | } | |
703 | Charset charset = this.charsetValueBuilder.getValue(); | |
704 |
1
1. buildCharset : negated conditional → SURVIVED |
if (charset != null) { |
705 |
4
1. buildCharset : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::buildCharset → KILLED 2. buildCharset : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::buildCharset → KILLED 3. buildCharset : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::buildCharset → KILLED 4. buildCharset : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::buildCharset → KILLED |
return buildContext.register(new FixedCharsetDetector(charset)); |
706 | } | |
707 |
3
1. buildCharset : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::buildCharset → NO_COVERAGE 2. buildCharset : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::buildCharset → KILLED 3. buildCharset : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::buildCharset → KILLED |
return buildContext.register(new FixedCharsetDetector()); |
708 | } | |
709 | ||
710 | private PropertyResolver getPropertyResolver() { | |
711 |
4
1. getPropertyResolver : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::getPropertyResolver → KILLED 2. getPropertyResolver : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::getPropertyResolver → KILLED 3. getPropertyResolver : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::getPropertyResolver → KILLED 4. getPropertyResolver : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::getPropertyResolver → KILLED |
return buildContext.getPropertyResolver(); |
712 | } | |
713 | ||
714 | private JavaMailAttachmentHandler buildAttachmentHandler(MimeTypeProvider mimetypeProvider) { | |
715 |
3
1. buildAttachmentHandler : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::buildAttachmentHandler → SURVIVED 2. buildAttachmentHandler : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::buildAttachmentHandler → KILLED 3. buildAttachmentHandler : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::buildAttachmentHandler → KILLED |
return buildContext.register(new JavaMailAttachmentHandler(buildAttachmentResourceHandler(mimetypeProvider))); |
716 | } | |
717 | ||
718 | private MapAttachmentResourceHandler buildAttachmentResourceHandler(MimeTypeProvider mimetypeProvider) { | |
719 | MapAttachmentResourceHandler resourceHandler = buildContext.register(new MapAttachmentResourceHandler()); | |
720 |
2
1. buildAttachmentResourceHandler : removed call to fr/sii/ogham/email/sender/impl/javamail/MapAttachmentResourceHandler::registerResourceHandler → SURVIVED 2. buildAttachmentResourceHandler : removed call to fr/sii/ogham/email/sender/impl/javamail/MapAttachmentResourceHandler::registerResourceHandler → KILLED |
resourceHandler.registerResourceHandler(FileResource.class, buildContext.register(new FileResourceHandler(mimetypeProvider))); |
721 |
1
1. buildAttachmentResourceHandler : removed call to fr/sii/ogham/email/sender/impl/javamail/MapAttachmentResourceHandler::registerResourceHandler → SURVIVED |
resourceHandler.registerResourceHandler(OverrideNameWrapper.class, buildContext.register(new OverrideNameWrapperResourceHandler(resourceHandler))); |
722 |
2
1. buildAttachmentResourceHandler : removed call to fr/sii/ogham/email/sender/impl/javamail/MapAttachmentResourceHandler::registerResourceHandler → SURVIVED 2. buildAttachmentResourceHandler : removed call to fr/sii/ogham/email/sender/impl/javamail/MapAttachmentResourceHandler::registerResourceHandler → KILLED |
resourceHandler.registerResourceHandler(LookupResource.class, buildContext.register(new FailResourceHandler(noResourceResolverConfigured()))); |
723 |
3
1. buildAttachmentResourceHandler : removed call to fr/sii/ogham/email/sender/impl/javamail/MapAttachmentResourceHandler::registerResourceHandler → SURVIVED 2. buildAttachmentResourceHandler : removed call to fr/sii/ogham/email/sender/impl/javamail/MapAttachmentResourceHandler::registerResourceHandler → KILLED 3. buildAttachmentResourceHandler : removed call to fr/sii/ogham/email/sender/impl/javamail/MapAttachmentResourceHandler::registerResourceHandler → KILLED |
resourceHandler.registerResourceHandler(NamedResource.class, buildContext.register(new StreamResourceHandler(mimetypeProvider))); |
724 |
3
1. buildAttachmentResourceHandler : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::buildAttachmentResourceHandler → SURVIVED 2. buildAttachmentResourceHandler : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::buildAttachmentResourceHandler → KILLED 3. buildAttachmentResourceHandler : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::buildAttachmentResourceHandler → KILLED |
return resourceHandler; |
725 | } | |
726 | ||
727 | private static BiFunction<NamedResource, Attachment, AttachmentResourceHandlerException> noResourceResolverConfigured() { | |
728 |
4
1. lambda$noResourceResolverConfigured$0 : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::lambda$noResourceResolverConfigured$0 → NO_COVERAGE 2. noResourceResolverConfigured : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::noResourceResolverConfigured → SURVIVED 3. lambda$noResourceResolverConfigured$0 : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::lambda$noResourceResolverConfigured$0 → KILLED 4. noResourceResolverConfigured : replaced return value with null for fr/sii/ogham/email/builder/javamail/JavaMailBuilder::noResourceResolverConfigured → KILLED |
return (resource, attachment) -> new UnresolvableAttachmentResourceHandlerException( |
729 | "Failed to attach " + resource.getName() + " because it points to a path but no resource resolver has been configured.", attachment); | |
730 | } | |
731 | ||
732 | private void updateProperties(Set<? extends Entry<?, ?>> entrySet) { | |
733 | for (Entry<?, ?> prop : entrySet) { | |
734 |
1
1. updateProperties : negated conditional → NO_COVERAGE |
if (prop.getValue() == null) { |
735 | additionalProperties.remove(prop.getKey()); | |
736 | } else { | |
737 | additionalProperties.setProperty(prop.getKey().toString(), prop.getValue().toString()); | |
738 | } | |
739 | } | |
740 | } | |
741 | } | |
Mutations | ||
252 |
1.1 2.2 3.3 |
|
253 |
1.1 2.2 3.3 |
|
293 |
1.1 2.2 3.3 4.4 |
|
331 |
1.1 2.2 |
|
332 |
1.1 2.2 |
|
372 |
1.1 2.2 3.3 4.4 |
|
410 |
1.1 |
|
411 |
1.1 |
|
451 |
1.1 2.2 3.3 4.4 |
|
469 |
1.1 |
|
487 |
1.1 2.2 3.3 4.4 |
|
490 |
1.1 2.2 3.3 4.4 |
|
510 |
1.1 |
|
534 |
1.1 |
|
587 |
1.1 2.2 3.3 4.4 |
|
590 |
1.1 2.2 3.3 4.4 |
|
613 |
1.1 |
|
630 |
1.1 |
|
631 |
1.1 |
|
649 |
1.1 2.2 |
|
650 |
1.1 2.2 |
|
660 |
1.1 2.2 3.3 4.4 |
|
666 |
1.1 2.2 3.3 4.4 |
|
670 |
1.1 2.2 3.3 4.4 |
|
674 |
1.1 2.2 3.3 4.4 |
|
678 |
1.1 2.2 3.3 4.4 |
|
682 |
1.1 2.2 |
|
683 |
1.1 |
|
685 |
1.1 2.2 3.3 |
|
686 |
1.1 2.2 |
|
693 |
1.1 2.2 3.3 |
|
694 |
1.1 2.2 |
|
695 |
1.1 2.2 3.3 4.4 |
|
696 |
1.1 2.2 3.3 4.4 |
|
700 |
1.1 2.2 3.3 4.4 |
|
701 |
1.1 |
|
704 |
1.1 |
|
705 |
1.1 2.2 3.3 4.4 |
|
707 |
1.1 2.2 3.3 |
|
711 |
1.1 2.2 3.3 4.4 |
|
715 |
1.1 2.2 3.3 |
|
720 |
1.1 2.2 |
|
721 |
1.1 |
|
722 |
1.1 2.2 |
|
723 |
1.1 2.2 3.3 |
|
724 |
1.1 2.2 3.3 |
|
728 |
1.1 2.2 3.3 4.4 |
|
734 |
1.1 |