diff --git a/Greenshot/Helpers/MailHelper.cs b/Greenshot/Helpers/MailHelper.cs index 74155fb0b..911f1d4f8 100644 --- a/Greenshot/Helpers/MailHelper.cs +++ b/Greenshot/Helpers/MailHelper.cs @@ -46,7 +46,7 @@ namespace Greenshot.Helpers { public class MapiMailMessage { private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(MapiMailMessage)); private static CoreConfiguration conf = IniConfig.GetIniSection(); - + /// /// Helper Method for creating an Email with Attachment /// @@ -61,12 +61,12 @@ namespace Greenshot.Helpers { if (!string.IsNullOrEmpty(conf.MailApiCC)) { message._recipientCollection.Add(new Recipient(conf.MailApiCC, RecipientType.CC)); } - if (!string.IsNullOrEmpty(conf.MailApiTo)) { + if (!string.IsNullOrEmpty(conf.MailApiBCC)) { message._recipientCollection.Add(new Recipient(conf.MailApiBCC, RecipientType.BCC)); } message.ShowDialog(); } - + /// /// Helper Method for creating an Email with Image Attachment @@ -92,7 +92,7 @@ namespace Greenshot.Helpers { } } #region Private MapiFileDescriptor Class - + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] private class MapiFileDescriptor { public int reserved = 0; @@ -102,11 +102,11 @@ namespace Greenshot.Helpers { public string name = null; public IntPtr type = IntPtr.Zero; } - + #endregion Private MapiFileDescriptor Class - + #region Enums - + /// /// Specifies the valid RecipientTypes for a Recipient. /// @@ -115,32 +115,32 @@ namespace Greenshot.Helpers { /// Recipient will be in the TO list. /// To = 1, - + /// /// Recipient will be in the CC list. /// CC = 2, - + /// /// Recipient will be in the BCC list. /// BCC = 3 }; - + #endregion Enums - + #region Member Variables - + private string _subject; private string _body; private RecipientCollection _recipientCollection; private List _files; private ManualResetEvent _manualResetEvent; - + #endregion Member Variables - + #region Constructors - + /// /// Creates a blank mail message. /// @@ -149,14 +149,14 @@ namespace Greenshot.Helpers { _recipientCollection = new RecipientCollection(); _manualResetEvent = new ManualResetEvent(false); } - + /// /// Creates a new mail message with the specified subject. /// public MapiMailMessage(string subject) : this() { _subject = subject; } - + /// /// Creates a new mail message with the specified subject and body. /// @@ -164,45 +164,57 @@ namespace Greenshot.Helpers { _subject = subject; _body = body; } - + #endregion Constructors - + #region Public Properties - + /// /// Gets or sets the subject of this mail message. /// public string Subject { - get { return _subject; } - set { _subject = value; } + get { + return _subject; + } + set { + _subject = value; + } } - + /// /// Gets or sets the body of this mail message. /// public string Body { - get { return _body; } - set { _body = value; } + get { + return _body; + } + set { + _body = value; + } } - + /// /// Gets the recipient list for this mail message. /// public RecipientCollection Recipients { - get { return _recipientCollection; } + get { + return _recipientCollection; + } } - + /// /// Gets the file list for this mail message. /// public List Files { - get { return _files; } + get { + return _files; + } } - + #endregion Public Properties - + #region Public Methods - + /// /// Displays the mail message dialog asynchronously. /// @@ -213,42 +225,42 @@ namespace Greenshot.Helpers { t.Name = "Create MAPI mail"; t.SetApartmentState(ApartmentState.STA); t.Start(); - + // only return when the new thread has built it's interop representation _manualResetEvent.WaitOne(); _manualResetEvent.Reset(); } - + #endregion Public Methods - + #region Private Methods - + /// /// Sends the mail message. /// private void _ShowMail() { MAPIHelperInterop.MapiMessage message = new MAPIHelperInterop.MapiMessage(); - + using (RecipientCollection.InteropRecipientCollection interopRecipients = _recipientCollection.GetInteropRepresentation()) { message.Subject = _subject; message.NoteText = _body; - + message.Recipients = interopRecipients.Handle; message.RecipientCount = _recipientCollection.Count; - + // Check if we need to add attachments if (_files.Count > 0) { // Add attachments message.Files = _AllocAttachments(out message.FileCount); } - + // Signal the creating thread (make the remaining code async) _manualResetEvent.Set(); - + const int MAPI_DIALOG = 0x8; //const int MAPI_LOGON_UI = 0x1; int error = MAPIHelperInterop.MAPISendMail(IntPtr.Zero, IntPtr.Zero, message, MAPI_DIALOG, 0); - + if (_files.Count > 0) { // Deallocate the files _DeallocFiles(message); @@ -268,23 +280,20 @@ namespace Greenshot.Helpers { } } } - + /// /// Deallocates the files in a message. /// /// The message to deallocate the files from. - private void _DeallocFiles(MAPIHelperInterop.MapiMessage message) - { - if (message.Files != IntPtr.Zero) - { + private void _DeallocFiles(MAPIHelperInterop.MapiMessage message) { + if (message.Files != IntPtr.Zero) { Type fileDescType = typeof(MapiFileDescriptor); int fsize = Marshal.SizeOf(fileDescType); - + // Get the ptr to the files int runptr = (int)message.Files; // Release each file - for (int i = 0; i < message.FileCount; i++) - { + for (int i = 0; i < message.FileCount; i++) { Marshal.DestroyStructure((IntPtr)runptr, fileDescType); runptr += fsize; } @@ -292,44 +301,40 @@ namespace Greenshot.Helpers { Marshal.FreeHGlobal(message.Files); } } - + /// /// Allocates the file attachments /// /// /// - private IntPtr _AllocAttachments(out int fileCount) - { + private IntPtr _AllocAttachments(out int fileCount) { fileCount = 0; - if (_files == null) - { + if (_files == null) { return IntPtr.Zero; } - if ((_files.Count <= 0) || (_files.Count > 100)) - { + if ((_files.Count <= 0) || (_files.Count > 100)) { return IntPtr.Zero; } - + Type atype = typeof(MapiFileDescriptor); int asize = Marshal.SizeOf(atype); IntPtr ptra = Marshal.AllocHGlobal(_files.Count * asize); - + MapiFileDescriptor mfd = new MapiFileDescriptor(); mfd.position = -1; int runptr = (int)ptra; - for (int i = 0; i < _files.Count; i++) - { + for (int i = 0; i < _files.Count; i++) { string path = _files[i] as string; mfd.name = Path.GetFileName(path); mfd.path = path; Marshal.StructureToPtr(mfd, (IntPtr)runptr, false); runptr += asize; } - + fileCount = _files.Count; return ptra; } - + private enum MAPI_CODES { SUCCESS = 0, USER_ABORT = 1, @@ -364,9 +369,9 @@ namespace Greenshot.Helpers { /// Logs any Mapi errors. /// private string GetMapiError(MAPI_CODES errorCode) { - + string error = string.Empty; - + switch (errorCode) { case MAPI_CODES.USER_ABORT: error = "User Aborted."; @@ -453,29 +458,27 @@ namespace Greenshot.Helpers { return error; } #endregion Private Methods - + #region Private MAPIHelperInterop Class - + /// /// Internal class for calling MAPI APIs /// - internal class MAPIHelperInterop - { + internal class MAPIHelperInterop { #region Constructors - + /// /// Private constructor. /// - private MAPIHelperInterop() - { + private MAPIHelperInterop() { // Intenationally blank } - + #endregion Constructors #region Structs - + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public class MapiMessage { public int Reserved = 0; @@ -491,7 +494,7 @@ namespace Greenshot.Helpers { public int FileCount = 0; public IntPtr Files = IntPtr.Zero; } - + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public class MapiRecipDesc { public int Reserved = 0; @@ -501,263 +504,239 @@ namespace Greenshot.Helpers { public int eIDSize = 0; public IntPtr EntryID = IntPtr.Zero; } - + [DllImport("MAPI32.DLL", SetLastError = true)] public static extern int MAPISendMail(IntPtr session, IntPtr hwnd, MapiMessage message, int flg, int rsv); - + #endregion Structs } - + #endregion Private MAPIHelperInterop Class } - + #endregion Public MapiMailMessage Class - + #region Public Recipient Class - + /// /// Represents a Recipient for a MapiMailMessage. /// - public class Recipient - { + public class Recipient { #region Public Properties - + /// /// The email address of this recipient. /// public string Address = null; - + /// /// The display name of this recipient. /// public string DisplayName = null; - + /// /// How the recipient will receive this message (To, CC, BCC). /// public MapiMailMessage.RecipientType RecipientType = MapiMailMessage.RecipientType.To; - + #endregion Public Properties - + #region Constructors - + /// /// Creates a new recipient with the specified address. /// - public Recipient(string address) - { + public Recipient(string address) { Address = address; } - + /// /// Creates a new recipient with the specified address and display name. /// - public Recipient(string address, string displayName) - { + public Recipient(string address, string displayName) { Address = address; DisplayName = displayName; } - + /// /// Creates a new recipient with the specified address and recipient type. /// - public Recipient(string address, MapiMailMessage.RecipientType recipientType) - { + public Recipient(string address, MapiMailMessage.RecipientType recipientType) { Address = address; RecipientType = recipientType; } - + /// /// Creates a new recipient with the specified address, display name and recipient type. /// - public Recipient(string address, string displayName, MapiMailMessage.RecipientType recipientType) - { + public Recipient(string address, string displayName, MapiMailMessage.RecipientType recipientType) { Address = address; DisplayName = displayName; RecipientType = recipientType; } - + #endregion Constructors - + #region Internal Methods - + /// /// Returns an interop representation of a recepient. /// /// - internal MapiMailMessage.MAPIHelperInterop.MapiRecipDesc GetInteropRepresentation() - { + internal MapiMailMessage.MAPIHelperInterop.MapiRecipDesc GetInteropRepresentation() { MapiMailMessage.MAPIHelperInterop.MapiRecipDesc interop = new MapiMailMessage.MAPIHelperInterop.MapiRecipDesc(); - - if (DisplayName == null) - { + + if (DisplayName == null) { interop.Name = Address; - } - else - { + } else { interop.Name = DisplayName; interop.Address = Address; } - + interop.RecipientClass = (int)RecipientType; - + return interop; } - + #endregion Internal Methods } - + #endregion Public Recipient Class - + #region Public RecipientCollection Class - + /// /// Represents a colleciton of recipients for a mail message. /// - public class RecipientCollection : CollectionBase - { + public class RecipientCollection : CollectionBase { /// /// Adds the specified recipient to this collection. /// - public void Add(Recipient value) - { + public void Add(Recipient value) { List.Add(value); } - + /// /// Adds a new recipient with the specified address to this collection. /// - public void Add(string address) - { + public void Add(string address) { this.Add(new Recipient(address)); } - + /// /// Adds a new recipient with the specified address and display name to this collection. /// - public void Add(string address, string displayName) - { + public void Add(string address, string displayName) { this.Add(new Recipient(address, displayName)); } - + /// /// Adds a new recipient with the specified address and recipient type to this collection. /// - public void Add(string address, MapiMailMessage.RecipientType recipientType) - { + public void Add(string address, MapiMailMessage.RecipientType recipientType) { this.Add(new Recipient(address, recipientType)); } - + /// /// Adds a new recipient with the specified address, display name and recipient type to this collection. /// - public void Add(string address, string displayName, MapiMailMessage.RecipientType recipientType) - { + public void Add(string address, string displayName, MapiMailMessage.RecipientType recipientType) { this.Add(new Recipient(address, displayName, recipientType)); } - + /// /// Returns the recipient stored in this collection at the specified index. /// - public Recipient this[int index] - { - get - { + public Recipient this[int index] { + get { return (Recipient)List[index]; } } - - internal InteropRecipientCollection GetInteropRepresentation() - { + + internal InteropRecipientCollection GetInteropRepresentation() { return new InteropRecipientCollection(this); } - + /// /// Struct which contains an interop representation of a colleciton of recipients. /// - internal struct InteropRecipientCollection : IDisposable - { + internal struct InteropRecipientCollection : IDisposable { #region Member Variables - + private IntPtr _handle; private int _count; - + #endregion Member Variables - + #region Constructors - + /// /// Default constructor for creating InteropRecipientCollection. /// /// - public InteropRecipientCollection(RecipientCollection outer) - { + public InteropRecipientCollection(RecipientCollection outer) { _count = outer.Count; - - if (_count == 0) - { + + if (_count == 0) { _handle = IntPtr.Zero; return; } - + // allocate enough memory to hold all recipients int size = Marshal.SizeOf(typeof(MapiMailMessage.MAPIHelperInterop.MapiRecipDesc)); _handle = Marshal.AllocHGlobal(_count * size); - + // place all interop recipients into the memory just allocated int ptr = (int)_handle; - foreach (Recipient native in outer) - { + foreach (Recipient native in outer) { MapiMailMessage.MAPIHelperInterop.MapiRecipDesc interop = native.GetInteropRepresentation(); - + // stick it in the memory block Marshal.StructureToPtr(interop, (IntPtr)ptr, false); ptr += size; } } - + #endregion Costructors - + #region Public Properties - - public IntPtr Handle - { - get { return _handle; } + + public IntPtr Handle { + get { + return _handle; + } } - + #endregion Public Properties - + #region Public Methods - + /// /// Disposes of resources. /// - public void Dispose() - { - if (_handle != IntPtr.Zero) - { + public void Dispose() { + if (_handle != IntPtr.Zero) { Type type = typeof(MapiMailMessage.MAPIHelperInterop.MapiRecipDesc); int size = Marshal.SizeOf(type); - + // destroy all the structures in the memory area int ptr = (int)_handle; - for (int i = 0; i < _count; i++) - { + for (int i = 0; i < _count; i++) { Marshal.DestroyStructure((IntPtr)ptr, type); ptr += size; } - + // free the memory Marshal.FreeHGlobal(_handle); - + _handle = IntPtr.Zero; _count = 0; } } - + #endregion Public Methods } } - - #endregion Public RecipientCollection Class -} + + #endregion Public RecipientCollection Class +} \ No newline at end of file diff --git a/Greenshot/releases/additional_files/readme.template.txt b/Greenshot/releases/additional_files/readme.template.txt index a77f40b9d..667969d1b 100644 --- a/Greenshot/releases/additional_files/readme.template.txt +++ b/Greenshot/releases/additional_files/readme.template.txt @@ -44,6 +44,7 @@ Bugs resolved (for bug details go to http://sourceforge.net/p/greenshot/bugs and * Not reported: When first selecting a printer, the main printer destination has been replaced by the selected one, making the Windows printer dialog unavailable for further prints * Not reported: Open last capture in explorer doesn't open the right location * Not reported: Fixed some issues where the sub-menus of the context menu moved to the next screen. +* Not reported: When having Outlook installed but not the Office plugin there was no EMail destination. Known issues: * Greenshot general: a captured I-Beam cursor isn't displayed correctly on the final result.