48
48
import java .net .InetAddress ;
49
49
import java .net .Socket ;
50
50
import java .util .*;
51
+ import java .util .regex .Pattern ;
51
52
52
53
/**
53
54
* eXist Mail Module Extension SendEmailFunction
@@ -70,6 +71,11 @@ public class SendEmailFunction extends BasicFunction {
70
71
71
72
private final static int MIME_BASE64_MAX_LINE_LENGTH = 76 ; //RFC 2045, page 24
72
73
74
+ /**
75
+ * Regular expression for checking for an RFC 2045 non-token.
76
+ */
77
+ private static final Pattern NON_TOKEN_PATTERN = Pattern .compile ("^.*[\\ s\\ p{Cntrl}()<>@,;:\\ \" /\\ [\\ ]?=].*$" );
78
+
73
79
private String charset ;
74
80
75
81
public final static FunctionSignature deprecated = new FunctionSignature (
@@ -568,10 +574,10 @@ private void writeMessage(final PrintWriter out, final Mail aMail, final boolean
568
574
for (final Iterator <MailAttachment > itAttachment = aMail .attachmentIterator (); itAttachment .hasNext (); ) {
569
575
final MailAttachment ma = itAttachment .next ();
570
576
571
- out .print ("Content-Type: " + ma .getMimeType () + "; name=\" " + ma .getFilename () + " \" " + eol );
577
+ out .print ("Content-Type: " + ma .getMimeType () + "; name=" + parameterValue ( ma .getFilename ()) + eol );
572
578
out .print ("Content-Transfer-Encoding: base64" + eol );
573
579
out .print ("Content-Description: " + ma .getFilename () + eol );
574
- out .print ("Content-Disposition: attachment; filename=\" " + ma .getFilename () + " \" " + eol );
580
+ out .print ("Content-Disposition: attachment; filename=" + parameterValue ( ma .getFilename ()) + eol );
575
581
out .print (eol );
576
582
577
583
@@ -1330,4 +1336,33 @@ public Iterator<MailAttachment> attachmentIterator() {
1330
1336
private static boolean nonEmpty (@ Nullable final String str ) {
1331
1337
return str != null && !str .isEmpty ();
1332
1338
}
1339
+
1340
+ /**
1341
+ * Creates a "quoted-string" of the parameter value
1342
+ * if it contains a non-token value (See {@link #isNonToken(String)}),
1343
+ * otherwise it returns the parameter value as is.
1344
+ *
1345
+ * @param value parameter value.
1346
+ *
1347
+ * @return the quoted string parameter value, or the parameter value as is.
1348
+ */
1349
+ private static String parameterValue (final String value ) {
1350
+ if (isNonToken (value )) {
1351
+ return "\" " + value + "\" " ;
1352
+ } else {
1353
+ return value ;
1354
+ }
1355
+ }
1356
+
1357
+ /**
1358
+ * Determines if the string contains SPACE, CTLs, or `tspecial` (special token)
1359
+ * according to <a href="https://www.rfc-editor.org/rfc/rfc2045#section-5">RFC 2045 - Section 5</a>.
1360
+ *
1361
+ * @param str the string to test
1362
+ *
1363
+ * @return true if the string contains a non-token, false otherwise.
1364
+ */
1365
+ private static boolean isNonToken (final String str ) {
1366
+ return NON_TOKEN_PATTERN .matcher (str ).matches ();
1367
+ }
1333
1368
}
0 commit comments