15 people like it.
Like the snippet!
Async SMTP
Async wrapper for SmtpClient (which is event-based)
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
|
open System
open System.Net
open System.Net.Mail
open System.Threading
/// from http://msdn.microsoft.com/en-us/magazine/cc163467.aspx
type internal AsyncResultNoResult(callback: AsyncCallback, state: obj) =
let statePending = 0
let stateCompletedSync = 1
let stateCompletedAsync = 2
let mutable completedState = statePending
let mutable waitHandle: ManualResetEvent = null
let mutable resultException: exn = null
interface IAsyncResult with
member x.AsyncState = state
member x.AsyncWaitHandle =
if waitHandle = null then
let isDone = (x :> IAsyncResult).IsCompleted
let mre = new ManualResetEvent(isDone)
if Interlocked.CompareExchange(&waitHandle, mre, null) <> null
then mre.Close()
else
if not isDone && (x :> IAsyncResult).IsCompleted
then waitHandle.Set() |> ignore
upcast waitHandle
member x.CompletedSynchronously =
Thread.VolatileRead(&completedState) = stateCompletedSync
member x.IsCompleted =
Thread.VolatileRead(&completedState) <> statePending
member x.SetAsCompleted(e: exn, completedSynchronously: bool) =
resultException <- e
let prevState = Interlocked.Exchange(&completedState, if completedSynchronously then stateCompletedSync else stateCompletedAsync)
if prevState <> statePending
then raise <| InvalidOperationException("You can set a result only once")
if waitHandle <> null
then waitHandle.Set() |> ignore
if callback <> null
then callback.Invoke(x)
member x.EndInvoke() =
let this = x :> IAsyncResult
if not this.IsCompleted then
this.AsyncWaitHandle.WaitOne() |> ignore
this.AsyncWaitHandle.Close()
waitHandle <- null
if resultException <> null
then raise resultException
type SmtpClient with
member private x.GetAsyncResult(callback, state) : IAsyncResult =
let r = AsyncResultNoResult(callback, state)
x.SendCompleted
|> Event.add(fun args -> r.SetAsCompleted(args.Error, false))
upcast r
member x.BeginSend(message: MailMessage, callback, state) =
let r = x.GetAsyncResult(callback, state)
x.SendAsync(message, null)
r
member x.BeginSend(from, recipients, subject, body, callback, state) =
let r = x.GetAsyncResult(callback, state)
x.SendAsync(from, recipients, subject, body, null)
r
member x.EndSend(result: IAsyncResult) =
let result = result :?> AsyncResultNoResult
result.EndInvoke()
member x.AsyncSend(message: MailMessage) =
Async.FromBeginEnd((fun(iar,state) -> x.BeginSend(message, iar, state)), x.EndSend, x.SendAsyncCancel)
member x.AsyncSend(from, recipients, subject, body) : Async<unit> =
Async.FromBeginEnd((fun(iar,state) -> x.BeginSend(from, recipients, subject, body, iar, state)), x.EndSend, x.SendAsyncCancel)
(*
// silly example
async {
let credentials = NetworkCredential("you@gmail.com", "yourpassword")
use smtp = new SmtpClient("smtp.gmail.com", 587, EnableSsl = true, Credentials = credentials)
do! smtp.AsyncSend("you@gmail.com", "your.email@gmail.com", "this subject", "cucamonga")
} |> Async.RunSynchronously
*)
|
namespace System
namespace System.Net
namespace System.Net.Mail
namespace System.Threading
Multiple items
type internal AsyncResultNoResult =
interface IAsyncResult
new : callback:AsyncCallback * state:obj -> AsyncResultNoResult
member EndInvoke : unit -> unit
member SetAsCompleted : e:exn * completedSynchronously:bool -> unit
Full name: Script.AsyncResultNoResult
from http://msdn.microsoft.com/en-us/magazine/cc163467.aspx
--------------------
internal new : callback:AsyncCallback * state:obj -> AsyncResultNoResult
val callback : AsyncCallback
type AsyncCallback =
delegate of IAsyncResult -> unit
Full name: System.AsyncCallback
val state : obj
type obj = Object
Full name: Microsoft.FSharp.Core.obj
val statePending : int
val stateCompletedSync : int
val stateCompletedAsync : int
val mutable completedState : int
val mutable waitHandle : ManualResetEvent
Multiple items
type ManualResetEvent =
inherit EventWaitHandle
new : initialState:bool -> ManualResetEvent
Full name: System.Threading.ManualResetEvent
--------------------
ManualResetEvent(initialState: bool) : unit
val mutable resultException : exn
type exn = Exception
Full name: Microsoft.FSharp.Core.exn
type IAsyncResult =
member AsyncState : obj
member AsyncWaitHandle : WaitHandle
member CompletedSynchronously : bool
member IsCompleted : bool
Full name: System.IAsyncResult
val x : AsyncResultNoResult
override internal AsyncResultNoResult.AsyncState : obj
Full name: Script.AsyncResultNoResult.AsyncState
override internal AsyncResultNoResult.AsyncWaitHandle : WaitHandle
Full name: Script.AsyncResultNoResult.AsyncWaitHandle
val isDone : bool
val mre : ManualResetEvent
type Interlocked =
static member Add : location1:int * value:int -> int + 1 overload
static member CompareExchange : location1:int * value:int * comparand:int -> int + 6 overloads
static member Decrement : location:int -> int + 1 overload
static member Exchange : location1:int * value:int -> int + 6 overloads
static member Increment : location:int -> int + 1 overload
static member Read : location:int64 -> int64
Full name: System.Threading.Interlocked
Interlocked.CompareExchange<'T (requires reference type)>(location1: byref<'T>, value: 'T, comparand: 'T) : 'T
Interlocked.CompareExchange(location1: byref<nativeint>, value: nativeint, comparand: nativeint) : nativeint
Interlocked.CompareExchange(location1: byref<obj>, value: obj, comparand: obj) : obj
Interlocked.CompareExchange(location1: byref<float>, value: float, comparand: float) : float
Interlocked.CompareExchange(location1: byref<float32>, value: float32, comparand: float32) : float32
Interlocked.CompareExchange(location1: byref<int64>, value: int64, comparand: int64) : int64
Interlocked.CompareExchange(location1: byref<int>, value: int, comparand: int) : int
WaitHandle.Close() : unit
val not : value:bool -> bool
Full name: Microsoft.FSharp.Core.Operators.not
EventWaitHandle.Set() : bool
val ignore : value:'T -> unit
Full name: Microsoft.FSharp.Core.Operators.ignore
override internal AsyncResultNoResult.CompletedSynchronously : bool
Full name: Script.AsyncResultNoResult.CompletedSynchronously
Multiple items
type Thread =
inherit CriticalFinalizerObject
new : start:ThreadStart -> Thread + 3 overloads
member Abort : unit -> unit + 1 overload
member ApartmentState : ApartmentState with get, set
member CurrentCulture : CultureInfo with get, set
member CurrentUICulture : CultureInfo with get, set
member DisableComObjectEagerCleanup : unit -> unit
member ExecutionContext : ExecutionContext
member GetApartmentState : unit -> ApartmentState
member GetCompressedStack : unit -> CompressedStack
member GetHashCode : unit -> int
...
Full name: System.Threading.Thread
--------------------
Thread(start: ThreadStart) : unit
Thread(start: ParameterizedThreadStart) : unit
Thread(start: ThreadStart, maxStackSize: int) : unit
Thread(start: ParameterizedThreadStart, maxStackSize: int) : unit
Thread.VolatileRead(address: byref<obj>) : obj
(+0 other overloads)
Thread.VolatileRead(address: byref<float>) : float
(+0 other overloads)
Thread.VolatileRead(address: byref<float32>) : float32
(+0 other overloads)
Thread.VolatileRead(address: byref<uint64>) : uint64
(+0 other overloads)
Thread.VolatileRead(address: byref<unativeint>) : unativeint
(+0 other overloads)
Thread.VolatileRead(address: byref<nativeint>) : nativeint
(+0 other overloads)
Thread.VolatileRead(address: byref<uint32>) : uint32
(+0 other overloads)
Thread.VolatileRead(address: byref<uint16>) : uint16
(+0 other overloads)
Thread.VolatileRead(address: byref<sbyte>) : sbyte
(+0 other overloads)
Thread.VolatileRead(address: byref<int64>) : int64
(+0 other overloads)
override internal AsyncResultNoResult.IsCompleted : bool
Full name: Script.AsyncResultNoResult.IsCompleted
member internal AsyncResultNoResult.SetAsCompleted : e:exn * completedSynchronously:bool -> unit
Full name: Script.AsyncResultNoResult.SetAsCompleted
val e : exn
val completedSynchronously : bool
type bool = Boolean
Full name: Microsoft.FSharp.Core.bool
val prevState : int
Interlocked.Exchange<'T (requires reference type)>(location1: byref<'T>, value: 'T) : 'T
Interlocked.Exchange(location1: byref<nativeint>, value: nativeint) : nativeint
Interlocked.Exchange(location1: byref<obj>, value: obj) : obj
Interlocked.Exchange(location1: byref<float>, value: float) : float
Interlocked.Exchange(location1: byref<float32>, value: float32) : float32
Interlocked.Exchange(location1: byref<int64>, value: int64) : int64
Interlocked.Exchange(location1: byref<int>, value: int) : int
val raise : exn:Exception -> 'T
Full name: Microsoft.FSharp.Core.Operators.raise
Multiple items
type InvalidOperationException =
inherit SystemException
new : unit -> InvalidOperationException + 2 overloads
Full name: System.InvalidOperationException
--------------------
InvalidOperationException() : unit
InvalidOperationException(message: string) : unit
InvalidOperationException(message: string, innerException: exn) : unit
AsyncCallback.Invoke(ar: IAsyncResult) : unit
member internal AsyncResultNoResult.EndInvoke : unit -> unit
Full name: Script.AsyncResultNoResult.EndInvoke
val this : IAsyncResult
property IAsyncResult.IsCompleted: bool
property IAsyncResult.AsyncWaitHandle: WaitHandle
WaitHandle.WaitOne() : bool
WaitHandle.WaitOne(timeout: TimeSpan) : bool
WaitHandle.WaitOne(millisecondsTimeout: int) : bool
WaitHandle.WaitOne(timeout: TimeSpan, exitContext: bool) : bool
WaitHandle.WaitOne(millisecondsTimeout: int, exitContext: bool) : bool
Multiple items
type SmtpClient =
new : unit -> SmtpClient + 2 overloads
member ClientCertificates : X509CertificateCollection
member Credentials : ICredentialsByHost with get, set
member DeliveryMethod : SmtpDeliveryMethod with get, set
member Dispose : unit -> unit
member EnableSsl : bool with get, set
member Host : string with get, set
member PickupDirectoryLocation : string with get, set
member Port : int with get, set
member Send : message:MailMessage -> unit + 1 overload
...
Full name: System.Net.Mail.SmtpClient
--------------------
SmtpClient() : unit
SmtpClient(host: string) : unit
SmtpClient(host: string, port: int) : unit
val x : SmtpClient
member private SmtpClient.GetAsyncResult : callback:AsyncCallback * state:'a -> IAsyncResult
Full name: Script.GetAsyncResult
val state : 'a
val r : AsyncResultNoResult
event SmtpClient.SendCompleted: IEvent<SendCompletedEventHandler,ComponentModel.AsyncCompletedEventArgs>
Multiple items
module Event
from Microsoft.FSharp.Control
--------------------
type Event<'T> =
new : unit -> Event<'T>
member Trigger : arg:'T -> unit
member Publish : IEvent<'T>
Full name: Microsoft.FSharp.Control.Event<_>
--------------------
type Event<'Delegate,'Args (requires delegate and 'Delegate :> Delegate)> =
new : unit -> Event<'Delegate,'Args>
member Trigger : sender:obj * args:'Args -> unit
member Publish : IEvent<'Delegate,'Args>
Full name: Microsoft.FSharp.Control.Event<_,_>
--------------------
new : unit -> Event<'T>
--------------------
new : unit -> Event<'Delegate,'Args>
val add : callback:('T -> unit) -> sourceEvent:IEvent<'Del,'T> -> unit (requires delegate and 'Del :> Delegate)
Full name: Microsoft.FSharp.Control.Event.add
val args : ComponentModel.AsyncCompletedEventArgs
member internal AsyncResultNoResult.SetAsCompleted : e:exn * completedSynchronously:bool -> unit
property ComponentModel.AsyncCompletedEventArgs.Error: exn
member SmtpClient.BeginSend : message:MailMessage * callback:AsyncCallback * state:'a -> IAsyncResult
Full name: Script.BeginSend
val message : MailMessage
Multiple items
type MailMessage =
new : unit -> MailMessage + 3 overloads
member AlternateViews : AlternateViewCollection
member Attachments : AttachmentCollection
member Bcc : MailAddressCollection
member Body : string with get, set
member BodyEncoding : Encoding with get, set
member CC : MailAddressCollection
member DeliveryNotificationOptions : DeliveryNotificationOptions with get, set
member Dispose : unit -> unit
member From : MailAddress with get, set
...
Full name: System.Net.Mail.MailMessage
--------------------
MailMessage() : unit
MailMessage(from: string, to: string) : unit
MailMessage(from: MailAddress, to: MailAddress) : unit
MailMessage(from: string, to: string, subject: string, body: string) : unit
val r : IAsyncResult
member private SmtpClient.GetAsyncResult : callback:AsyncCallback * state:'a -> IAsyncResult
SmtpClient.SendAsync(message: MailMessage, userToken: obj) : unit
SmtpClient.SendAsync(from: string, recipients: string, subject: string, body: string, userToken: obj) : unit
member SmtpClient.BeginSend : from:string * recipients:string * subject:string * body:string * callback:AsyncCallback * state:'a -> IAsyncResult
Full name: Script.BeginSend
val from : string
val recipients : string
val subject : string
val body : string
member SmtpClient.EndSend : result:IAsyncResult -> unit
Full name: Script.EndSend
val result : IAsyncResult
val result : AsyncResultNoResult
member internal AsyncResultNoResult.EndInvoke : unit -> unit
member SmtpClient.AsyncSend : message:MailMessage -> Async<unit>
Full name: Script.AsyncSend
Multiple items
type Async
static member AsBeginEnd : computation:('Arg -> Async<'T>) -> ('Arg * AsyncCallback * obj -> IAsyncResult) * (IAsyncResult -> 'T) * (IAsyncResult -> unit)
static member AwaitEvent : event:IEvent<'Del,'T> * ?cancelAction:(unit -> unit) -> Async<'T> (requires delegate and 'Del :> Delegate)
static member AwaitIAsyncResult : iar:IAsyncResult * ?millisecondsTimeout:int -> Async<bool>
static member AwaitTask : task:Task<'T> -> Async<'T>
static member AwaitWaitHandle : waitHandle:WaitHandle * ?millisecondsTimeout:int -> Async<bool>
static member CancelDefaultToken : unit -> unit
static member Catch : computation:Async<'T> -> Async<Choice<'T,exn>>
static member FromBeginEnd : beginAction:(AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromBeginEnd : arg:'Arg1 * beginAction:('Arg1 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * beginAction:('Arg1 * 'Arg2 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * arg3:'Arg3 * beginAction:('Arg1 * 'Arg2 * 'Arg3 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromContinuations : callback:(('T -> unit) * (exn -> unit) * (OperationCanceledException -> unit) -> unit) -> Async<'T>
static member Ignore : computation:Async<'T> -> Async<unit>
static member OnCancel : interruption:(unit -> unit) -> Async<IDisposable>
static member Parallel : computations:seq<Async<'T>> -> Async<'T []>
static member RunSynchronously : computation:Async<'T> * ?timeout:int * ?cancellationToken:CancellationToken -> 'T
static member Sleep : millisecondsDueTime:int -> Async<unit>
static member Start : computation:Async<unit> * ?cancellationToken:CancellationToken -> unit
static member StartAsTask : computation:Async<'T> * ?taskCreationOptions:TaskCreationOptions * ?cancellationToken:CancellationToken -> Task<'T>
static member StartChild : computation:Async<'T> * ?millisecondsTimeout:int -> Async<Async<'T>>
static member StartChildAsTask : computation:Async<'T> * ?taskCreationOptions:TaskCreationOptions -> Async<Task<'T>>
static member StartImmediate : computation:Async<unit> * ?cancellationToken:CancellationToken -> unit
static member StartWithContinuations : computation:Async<'T> * continuation:('T -> unit) * exceptionContinuation:(exn -> unit) * cancellationContinuation:(OperationCanceledException -> unit) * ?cancellationToken:CancellationToken -> unit
static member SwitchToContext : syncContext:SynchronizationContext -> Async<unit>
static member SwitchToNewThread : unit -> Async<unit>
static member SwitchToThreadPool : unit -> Async<unit>
static member TryCancelled : computation:Async<'T> * compensation:(OperationCanceledException -> unit) -> Async<'T>
static member CancellationToken : Async<CancellationToken>
static member DefaultCancellationToken : CancellationToken
Full name: Microsoft.FSharp.Control.Async
--------------------
type Async<'T>
Full name: Microsoft.FSharp.Control.Async<_>
static member Async.FromBeginEnd : beginAction:(AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member Async.FromBeginEnd : arg:'Arg1 * beginAction:('Arg1 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member Async.FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * beginAction:('Arg1 * 'Arg2 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member Async.FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * arg3:'Arg3 * beginAction:('Arg1 * 'Arg2 * 'Arg3 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
val iar : AsyncCallback
member SmtpClient.BeginSend : message:MailMessage * callback:AsyncCallback * state:'a -> IAsyncResult
member SmtpClient.BeginSend : from:string * recipients:string * subject:string * body:string * callback:AsyncCallback * state:'a -> IAsyncResult
member SmtpClient.EndSend : result:IAsyncResult -> unit
SmtpClient.SendAsyncCancel() : unit
member SmtpClient.AsyncSend : from:string * recipients:string * subject:string * body:string -> Async<unit>
Full name: Script.AsyncSend
type unit = Unit
Full name: Microsoft.FSharp.Core.unit
More information