Outlook AddIn Anhänge extrahieren

    • C#
    • .NET (FX) 4.5–4.8

      Outlook AddIn Anhänge extrahieren

      Hallo Leute,

      in diesem Thread ein wenig Code, der zeigt wie man Anhänge aus gerade erstellten E-Mails in Outlook extrahiert.
      Ist dann sinnvoll, oder von Nutzen, wenn man diese Dateien Beispielsweise verschlüsseln möchte vor dem Senden.

      Zu beachten ist, dass pre PropertyAccessor in C#, nur relativ kleine Anhänge extrahiert werden können.
      Daher gibt es im folgenden Code die Funktion GetLargeBytes(), welche keinen MAPI Proptag verwendet um an die Bytes des Anhangs zu kommen.
      Große Anhänge können, meines wissens nach, nur mit extended MAPI extrahiert werden, was nur in C++ und Delphi möglich ist.

      Klasse zum extrahieren der Anhänge:
      Spoiler anzeigen

      C#-Quellcode

      1. using Outlook = Microsoft.Office.Interop.Outlook;
      2. /// <summary>
      3. /// Class to receive and add Outlook Attachments
      4. /// </summary>
      5. public static class AttachmentManager
      6. {
      7. /// <summary>
      8. /// Gets an attachment as byte array
      9. /// </summary>
      10. /// <param name="mailItem"><see cref="Outlook.MailItem"/> which contains the attachment</param>
      11. /// <param name="fileName">Filename of the desired attachment</param>
      12. /// <returns>Returns the specific attachment as byte array</returns>
      13. public static byte[] GetAttachment(Outlook.MailItem mailItem, string fileName)
      14. {
      15. if (mailItem == null) return new byte[0];
      16. if (mailItem.Attachments.Count <= 0) return new byte[0];
      17. if (string.IsNullOrEmpty(fileName)) return new byte[0];
      18. /* MAPI propertytag name (not a actual website) */
      19. const string PR_ATTACH_DATA_BIN = "http://schemas.microsoft.com/mapi/proptag/0x37010102";
      20. /* Index of found attachment incase that it is too big for property accessor. */
      21. int idx = -1;
      22. try
      23. {
      24. for (int i=1; i<=mailItem.Attachments.Count; i++)
      25. {
      26. if (mailItem.Attachments[i].FileName == fileName)
      27. {
      28. idx = i;
      29. /* Get attachment as file array via PropertyAcessor and PR_ATTACH_DATA_BIN tag.
      30. ** https://docs.microsoft.com/en-us/previous-versions/exchange-server/exchange-10/ms526356(v=exchg.10)
      31. ** Will fail if attachment exceeds certain size if using normal MAPI.
      32. ** Large files require extended MAPI which only works with C++ and Delphi. */
      33. return mailItem.Attachments[i].PropertyAccessor.GetProperty(PR_ATTACH_DATA_BIN);
      34. }
      35. }
      36. return new byte[0];
      37. }
      38. catch (System.Runtime.InteropServices.COMException)
      39. {
      40. if (idx < 1) return new byte[0];
      41. /* If file was too big for PropertyAccessor call GetLargetBytes() function. */
      42. return GetLargeBytes(mailItem.Attachments[idx]);
      43. }
      44. catch
      45. {
      46. return new byte[0];
      47. }
      48. }
      49. /*
      50. ** Function to get large attachments as byte array without using PropertyAccessor and MAPI tag.
      51. ** Will be heavy on filesystem if used extensively. Writes, reades and deletes files.
      52. **
      53. ** Returns file as byte array
      54. ** Returns émpty byte array if any exception was thrown
      55. */
      56. private static byte[] GetLargeBytes(Outlook.Attachment attachment)
      57. {
      58. byte[] result = null;
      59. try
      60. {
      61. string path = System.IO.Path.Combine(
      62. System.IO.Path.GetTempPath(),
      63. System.IO.Path.GetTempFileName());
      64. /* Save attachment on disk with generated TEMP path and name*/
      65. attachment.SaveAsFile(path);
      66. /* Load saved attachment into FileStream with 4k buffersize.
      67. ** I recommend keeping that buffersize since I/O speed is dominated by disk drive and
      68. ** CPU cache can easily hold that much. The .net default buffersize is 4k but
      69. ** in .net 4.5 they increased it to 80k which is a bit much in my opinion... */
      70. using (var mem = new System.IO.MemoryStream())
      71. using (var stream = new System.IO.FileStream(
      72. path,
      73. System.IO.FileMode.Open,
      74. System.IO.FileAccess.Read,
      75. System.IO.FileShare.None,
      76. 0x1000))
      77. {
      78. stream.CopyTo(mem);
      79. result = mem.ToArray();
      80. }
      81. System.IO.File.Delete(path);
      82. return result;
      83. }
      84. catch
      85. {
      86. return new byte[0];
      87. }
      88. }
      89. }




      Erstelle E-Mail bekommen in Klasse welche sich im Projekt von ThisAddIn befindet:
      Spoiler anzeigen

      C#-Quellcode

      1. using Outlook = Microsoft.Office.Interop.Outlook;
      2. public class Some_Class_In_Namespace_of_ThisAddin
      3. {
      4. /*
      5. ** Function to get the top most MailItem from current Outlook instance.
      6. ** Uses the Outlook application instance in which the AddIn runs.
      7. ** Uses the Microsoft.Office.Interop.Outlook.ActiveInspector object to get the Mail.
      8. **
      9. ** Returns MailItem if there is one
      10. ** Returns null if anything failed
      11. */
      12. private Outlook.MailItem GetMailItem()
      13. {
      14. var olApp = (Outlook.Application)Globals.ThisAddIn.Application;
      15. if (olApp == null) return null;
      16. var olInp = (Outlook.Inspector)olApp.ActiveInspector();
      17. if (olInp == null) return null;
      18. var olMal = (Outlook.MailItem)olInp.CurrentItem;
      19. return olMal;
      20. }
      21. /*
      22. ** Function to get a MailItem which is currently beeing edited (like a response MailItem).
      23. ** Uses the Outlook application instance in which the AddIn runs.
      24. ** Uses the Microsoft.Office.Interop._Explorer.ActiveInlineResponse object to get the Mail.
      25. **
      26. ** Returns MailItem if there is one
      27. ** Returns null if anything failed
      28. */
      29. private Outlook.MailItem GetResponseItem()
      30. {
      31. var olApp = (Outlook.Application)Globals.ThisAddIn.Application;
      32. if (olApp == null) return null;
      33. var olExplorer = (Outlook.Explorer)olApp.ActiveExplorer();
      34. if (olExplorer == null) return null;
      35. var olInlineResponse = (Outlook.MailItem)olExplorer.ActiveInlineResponse;
      36. return olInlineResponse;
      37. }
      38. }




      Erstelle E-Mail bekommen in custom Ribbon:
      Spoiler anzeigen

      C#-Quellcode

      1. using Outlook = Microsoft.Office.Interop.Outlook;
      2. using Core = Microsoft.Office.Core;
      3. public Ribbon_Example : Core.IRibbonExtensibility
      4. {
      5. /*
      6. ** Callback of Ribbon Button to get current compose MailItem
      7. */
      8. public void Btn_GetCompose_Click(Core.IRibbonControl control)
      9. {
      10. var composeMailItem = GetResponseMailItem(control);
      11. }
      12. /*
      13. ** Callback of Ribbon Button to get newly created MailItem
      14. */
      15. public void Btn_GetNew_Click(Core.IRibbonControl control)
      16. {
      17. var newMailItem = GetMailItem(control);
      18. }
      19. /*
      20. ** Function to get the topmost mail item from current inspector
      21. */
      22. private Outlook.MailItem GetMailItem(Core.IRibbonControl control)
      23. {
      24. if (!(control.Context is Outlook.Inspector item)) return null;
      25. var mailItem = item.CurrentItem as Outlook.MailItem;
      26. return mailItem;
      27. }
      28. /*
      29. ** Function to get topmost composing mail item from current explorer
      30. */
      31. private Outlook.MailItem GetResponseMailItem(Core.IRibbonControl control)
      32. {
      33. if (!(control.Context is Outlook.Explorer item)) return null;
      34. var response = item.ActiveInlineResponse as Outlook.MailItem;
      35. return response;
      36. }
      37. }