Ejemplo n.º 1
0
 public static void SingleTestMediaTypeEncoding(string value)
 {
     MediaType mt = new MediaTypeBuilder(
       "x",
       "y").SetParameter(
       "z",
       value).ToMediaType();
       string topLevel = mt.TopLevelType;
       string sub = mt.SubType;
       string mtstring = "MIME-Version: 1.0\r\nContent-Type: " + mt +
     "\r\nContent-Transfer-Encoding: base64\r\n\r\n";
       Message msg = MessageFromString(mtstring);
       Assert.AreEqual(topLevel, msg.ContentType.TopLevelType);
       Assert.AreEqual(sub, msg.ContentType.SubType);
       Assert.AreEqual(
       value,
       msg.ContentType.GetParameter("z"),
       mt.ToString());
 }
Ejemplo n.º 2
0
    private void Generate(IWriter output, int depth) {
      var haveMimeVersion = false;
      var haveContentEncoding = false;
      var haveContentType = false;
      var haveContentDisp = false;
      var haveMsgId = false;
      var haveFrom = false;
      var haveDate = false;
      var haveHeaders = new bool[11];
      byte[] bodyToWrite = this.body;
      var builder = new MediaTypeBuilder(this.ContentType);
      string contentDisp = (this.ContentDisposition == null) ? null :
        this.ContentDisposition.ToString();
      var transferEnc = 0;
      var isMultipart = false;
      string boundary = String.Empty;
      if (builder.IsMultipart) {
        boundary = GenerateBoundary(depth);
        builder.SetParameter("boundary", boundary);
        isMultipart = true;
      }
      if (!isMultipart) {
        if (builder.TopLevelType.Equals("message")) {
          if (builder.SubType.Equals("delivery-status") ||
              builder.SubType.Equals("global-delivery-status")) {
            bodyToWrite = DowngradeDeliveryStatus(bodyToWrite);
          }
          bool msgCanBeUnencoded = CanBeUnencoded(bodyToWrite, depth > 0);
          if ((builder.SubType.Equals("rfc822") || builder.SubType.Equals(
            "news")) && !msgCanBeUnencoded) {
            builder.SetSubType("global");
          } else if (builder.SubType.Equals("disposition-notification") &&
                    !msgCanBeUnencoded) {
            builder.SetSubType("global-disposition-notification");
          } else if (builder.SubType.Equals("delivery-status") &&
                    !msgCanBeUnencoded) {
            builder.SetSubType("global-delivery-status");
          } else if (!msgCanBeUnencoded && !builder.SubType.Equals("global") &&
            !builder.SubType.Equals("global-disposition-notification") &&
            !builder.SubType.Equals("global-delivery-status") &&
            !builder.SubType.Equals("global-headers")) {
#if DEBUG
            throw new MessageDataException("Message body can't be encoded: " +
              builder.ToString() + ", " + this.ContentType);
#else
{
 throw new MessageDataException("Message body can't be encoded");
}
#endif
          }
        }
      }
      string topLevel = builder.TopLevelType;
      transferEnc = topLevel.Equals("message") ||
        topLevel.Equals("multipart") ? (topLevel.Equals("multipart") || (
          !builder.SubType.Equals("global") &&
          !builder.SubType.Equals("global-headers") &&
          !builder.SubType.Equals("global-disposition-notification") &&
          !builder.SubType.Equals("global-delivery-status"))) ?
          EncodingSevenBit : TransferEncodingToUse(
            bodyToWrite,
            depth > 0) : TransferEncodingToUse(bodyToWrite, depth > 0);
      string encodingString = "7bit";
      if (transferEnc == EncodingBase64) {
        encodingString = "base64";
      } else if (transferEnc == EncodingQuotedPrintable) {
        encodingString = "quoted-printable";
      }
      // Write the header fields
      for (int i = 0; i < this.headers.Count; i += 2) {
        string name = this.headers[i];
        string value = this.headers[i + 1];
        if (name.Equals("content-type")) {
          if (haveContentType) {
            // Already outputted, continue
            continue;
          }
          haveContentType = true;
          value = builder.ToString();
        }
        if (name.Equals("content-disposition")) {
          if (haveContentDisp || contentDisp == null) {
            // Already outputted, continue
            continue;
          }
          haveContentDisp = true;
          value = contentDisp;
        } else if (name.Equals("content-transfer-encoding")) {
          if (haveContentEncoding) {
            // Already outputted, continue
            continue;
          }
          haveContentEncoding = true;
          value = encodingString;
        } else if (name.Equals("date")) {
          if (haveDate) {
            continue;
          }
          haveDate = true;
        } else if (name.Equals("from")) {
          if (haveFrom) {
            // Already outputted, continue
            continue;
          }
          haveFrom = true;
        }
        if (
          depth > 0 && (
            name.Length < 8 || !name.Substring(
              0,
              8).Equals("content-"))) {
          // don't generate header fields not starting with "Content-"
          // in body parts
          continue;
        }
        if (name.Equals("mime-version")) {
          haveMimeVersion = true;
        } else if (name.Equals("message-id")) {
          if (haveMsgId) {
            // Already outputted, continue
            continue;
          }
          haveMsgId = true;
        } else {
          if (ValueHeaderIndices.ContainsKey(name)) {
            int headerIndex = ValueHeaderIndices[name];
            if (headerIndex < 9) {
              if (haveHeaders[headerIndex]) {
                // Already outputted, continue
                continue;
              }
              haveHeaders[headerIndex] = true;
              if (!this.IsValidAddressingField(name)) {
                value = GenerateAddressList(
    ParseAddresses(this.GetMultipleHeaders(name)));
                if (value.Length == 0) {
                  // No addresses, synthesize a field
                  value = this.SynthesizeField(name);
                }
              }
            }
            if (headerIndex == 9 || headerIndex == 10) {
              // Resent-From/Resent-Sender, can appear
              // more than once
              value = GenerateAddressList(ParseAddresses(value));
              if (value.Length == 0) {
                // No addresses, synthesize a field
                value = this.SynthesizeField(name);
              }
            }
          }
        }
        string rawField = Capitalize(name) + ":" +
          (StartsWithWhitespace(value) ? String.Empty : " ") + value;
        if (CanOutputRaw(rawField)) {
          AppendAscii(output, rawField);
          if (rawField.IndexOf(": ", StringComparison.Ordinal) < 0) {
            throw new MessageDataException("No colon+space: " + rawField);
          }
        } else if (HasTextToEscape(value)) {
          string downgraded =
            HeaderFieldParsers.GetParser(name).DowngradeFieldValue(value);
          if (
            HasTextToEscapeIgnoreEncodedWords(
              downgraded,
              0,
              downgraded.Length)) {
            if (name.Equals("message-id") ||
                name.Equals("resent-message-id") || name.Equals(
                "in-reply-to") || name.Equals("references") || name.Equals(
                "original-recipient") || name.Equals("final-recipient")) {
              // Header field still contains invalid characters (such
              // as non-ASCII characters in 7-bit messages), convert
              // to a downgraded field
              name = "downgraded-" + name;
              downgraded =
                    Rfc2047.EncodeString(ParserUtility.TrimSpaceAndTab(value));
            } else {
#if DEBUG
              throw new
  MessageDataException("Header field still has non-Ascii or controls: " +
                    name + " " + value);
#else
               throw new MessageDataException(
                 "Header field still has non-Ascii or controls");
#endif
            }
          }
          bool haveDquote = downgraded.IndexOf('"') >= 0;
          var encoder = new WordWrapEncoder(!haveDquote);
          encoder.AddString(Capitalize(name) + ": " + downgraded);
          string newValue = encoder.ToString();
          AppendAscii(output, newValue);
        } else {
          bool haveDquote = value.IndexOf('"') >= 0;
          var encoder = new WordWrapEncoder(!haveDquote);
          encoder.AddString(Capitalize(name) + ": " + value);
          string newValue = encoder.ToString();
          AppendAscii(output, newValue);
        }
        AppendAscii(output, "\r\n");
      }
      if (!haveFrom && depth == 0) {
        // Output a synthetic From field if it doesn't
        // exist and this isn't a body part
        AppendAscii(output, "From: [email protected]\r\n");
      }
      if (!haveDate && depth == 0) {
        AppendAscii(output, "Date: ");
        AppendAscii(
          output,
          GetDateString(DateTimeUtilities.GetCurrentLocalTime()));
        AppendAscii(output, "\r\n");
      }
      if (!haveMsgId && depth == 0) {
        AppendAscii(output, "Message-ID:\r\n ");
        AppendAscii(output, this.GenerateMessageID());
        AppendAscii(output, "\r\n");
      }
      if (!haveMimeVersion && depth == 0) {
        AppendAscii(output, "MIME-Version: 1.0\r\n");
      }
      if (!haveContentType) {
        AppendAscii(output, "Content-Type: " + builder + "\r\n");
      }
      if (!haveContentEncoding) {
        AppendAscii(
      output,
      "Content-Transfer-Encoding: " + encodingString + "\r\n");
      }
      ICharacterEncoder bodyEncoder = null;
      switch (transferEnc) {
        case EncodingBase64:
          bodyEncoder = new Base64Encoder(true, builder.IsText, false);
          break;
        case EncodingQuotedPrintable:
          bodyEncoder = new QuotedPrintableEncoder(
            builder.IsText ? 2 : 0,
            false);
          break;
        default:
          bodyEncoder = new IdentityEncoder();
          break;
      }
      // Write the body
      AppendAscii(output, "\r\n");
      if (!isMultipart) {
        var index = 0;
        while (true) {
          int c = (index >= bodyToWrite.Length) ? -1 :
            ((int)bodyToWrite[index++]) & 0xff;
          int count = bodyEncoder.Encode(c, output);
          if (count == -2) {
            throw new MessageDataException("encoding error");
          }
          if (count == -1) {
            break;
          }
        }
      } else {
        foreach (Message part in this.Parts) {
          AppendAscii(output, "\r\n--" + boundary + "\r\n");
          part.Generate(output, depth + 1);
        }
        AppendAscii(output, "\r\n--" + boundary + "--");
      }
    }