Skip to content

Commit

Permalink
Allow SmtpClient subclasses to override message preparation
Browse files Browse the repository at this point in the history
Fixes issue #891
  • Loading branch information
jstedfast committed Aug 7, 2019
1 parent b395841 commit 4dcc89b
Showing 1 changed file with 48 additions and 23 deletions.
71 changes: 48 additions & 23 deletions MailKit/Net/Smtp/SmtpClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1621,23 +1621,27 @@ enum SmtpExtension {

class ContentTransferEncodingVisitor : MimeVisitor
{
public SmtpExtension SmtpExtensions {
get; private set;
}
readonly SmtpCapabilities capabilities;

protected override void VisitMultipartSigned (MultipartSigned signed)
public ContentTransferEncodingVisitor (SmtpCapabilities capabilities)
{
// do not modify children of a multipart/signed
this.capabilities = capabilities;
}

public SmtpExtension SmtpExtensions {
get; private set;
}

protected override void VisitMimePart (MimePart entity)
{
switch (entity.ContentTransferEncoding) {
case ContentEncoding.EightBit:
SmtpExtensions |= SmtpExtension.EightBitMime;
if ((capabilities & SmtpCapabilities.EightBitMime) != 0)
SmtpExtensions |= SmtpExtension.EightBitMime;
break;
case ContentEncoding.Binary:
SmtpExtensions |= SmtpExtension.BinaryMime;
if ((capabilities & SmtpCapabilities.BinaryMime) != 0)
SmtpExtensions |= SmtpExtension.BinaryMime;
break;
}
}
Expand Down Expand Up @@ -2013,6 +2017,32 @@ async Task ResetAsync (bool doAsync, CancellationToken cancellationToken)
}
}

/// <summary>
/// Prepare the message for transport with the specified constraints.
/// </summary>
/// <remarks>
/// <para>Prepares the message for transport with the specified constraints.</para>
/// <para>Typically, this involves calling <see cref="MimeMessage.Prepare(EncodingConstraint, int)"/> on
/// the message with the provided constraints.</para>
/// </remarks>
/// <param name="options">The format options.</param>
/// <param name="message">The message.</param>
/// <param name="constraint">The encoding constraint.</param>
/// <param name="maxLineLength">The max line length supported by the server.</param>
protected virtual void Prepare (FormatOptions options, MimeMessage message, EncodingConstraint constraint, int maxLineLength)
{
if (!message.Headers.Contains (HeaderId.DomainKeySignature) &&
!message.Headers.Contains (HeaderId.DkimSignature) &&
!message.Headers.Contains (HeaderId.ArcSeal)) {
// prepare the message
message.Prepare (constraint, maxLineLength);
} else {
// Note: we do not want to risk reformatting of headers to the international
// UTF-8 encoding, so disable it.
options.International = false;
}
}

async Task SendAsync (FormatOptions options, MimeMessage message, MailboxAddress sender, IList<MailboxAddress> recipients, bool doAsync, CancellationToken cancellationToken, ITransferProgress progress)
{
CheckDisposed ();
Expand All @@ -2030,24 +2060,19 @@ async Task SendAsync (FormatOptions options, MimeMessage message, MailboxAddress
if (format.International && (Capabilities & SmtpCapabilities.EightBitMime) == 0)
throw new NotSupportedException ("The SMTP server does not support the 8BITMIME extension.");

if (!message.Headers.Contains (HeaderId.DomainKeySignature) &&
!message.Headers.Contains (HeaderId.DkimSignature) &&
!message.Headers.Contains (HeaderId.ArcSeal)) {
// prepare the message
if ((Capabilities & SmtpCapabilities.BinaryMime) != 0)
message.Prepare (EncodingConstraint.None, MaxLineLength);
else if ((Capabilities & SmtpCapabilities.EightBitMime) != 0)
message.Prepare (EncodingConstraint.EightBit, MaxLineLength);
else
message.Prepare (EncodingConstraint.SevenBit, MaxLineLength);
} else {
// Note: we do not want to risk reformatting of headers to the international
// UTF-8 encoding, so disable it.
format.International = false;
}
EncodingConstraint constraint;

if ((Capabilities & SmtpCapabilities.BinaryMime) != 0)
constraint = EncodingConstraint.None;
else if ((Capabilities & SmtpCapabilities.EightBitMime) != 0)
constraint = EncodingConstraint.EightBit;
else
constraint = EncodingConstraint.SevenBit;

Prepare (options, message, constraint, MaxLineLength);

// figure out which SMTP extensions we need to use
var visitor = new ContentTransferEncodingVisitor ();
var visitor = new ContentTransferEncodingVisitor (capabilities);
visitor.Visit (message);

var extensions = visitor.SmtpExtensions;
Expand Down

0 comments on commit 4dcc89b

Please sign in to comment.