package async_smtp

  1. Overview
  2. Docs
SMTP client and server

Install

Dune Dependency

Authors

Maintainers

Sources

v0.17.0.tar.gz
sha256=c416027c2537e22129f7049bf03ec3f867557d47b194d7e91d72c399fe656b27

doc/src/async_smtp.types/sender.ml.html

Source file sender.ml

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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
module Stable0 = struct
  open! Core.Core_stable

  module V1_no_sexp = struct
    type t =
      [ `Null
      | `Email of Email_address.Stable.V1.t
      ]
    [@@deriving bin_io, compare, hash]

    let%expect_test _ =
      print_endline [%bin_digest: t];
      [%expect {| 8dd845baf982d3fc6ad2baf59cd9b41f |}]
    ;;
  end
end

open! Core
open Or_error.Let_syntax

module T = struct
  type t =
    [ `Null
    | `Email of Email_address.t
    ]
  [@@deriving compare, hash]

  let to_string = function
    | `Null -> "<>"
    | `Email email -> Email_address.to_string email
  ;;

  let sexp_of_t t = sexp_of_string (to_string t)
end

include T
include Hashable.Make_plain (T)
include Comparable.Make_plain (T)

let of_string_with_arguments ?default_domain ~allowed_extensions str =
  let%bind mail_from =
    Or_error.try_with (fun () -> Mail_from_lexer.parse_mail_from (Lexing.from_string str))
    |> Or_error.tag ~tag:(sprintf "Failed to parse [Sender.t] from \"%s\"" str)
  in
  let%bind all_args =
    Sender_argument.list_of_string ~allowed_extensions mail_from.suffix
  in
  match mail_from.sender with
  | `Null -> Ok (`Null, all_args)
  | `Email email ->
    let domain = Option.first_some email.domain default_domain in
    let email_address =
      Email_address.create ?prefix:mail_from.prefix ?domain email.local_part
    in
    Ok (`Email email_address, all_args)
;;

let of_string ?default_domain str =
  match%map of_string_with_arguments ?default_domain ~allowed_extensions:[] str with
  | email, [] -> email
  | _, _ :: _ -> failwithf "impossible, unexpected extension arguments" ()
;;

let of_string_exn ?default_domain str = of_string ?default_domain str |> Or_error.ok_exn

let to_string_with_arguments (sender, args) =
  to_string sender :: List.map args ~f:Sender_argument.to_string |> String.concat ~sep:" "
;;

let map t ~f =
  match t with
  | `Null -> t
  | `Email email -> `Email (f email)
;;

module Caseless = struct
  module T = struct
    type nonrec t =
      (* t = *)
      [ `Null
      | `Email of Email_address.Caseless.t
      ]
    [@@deriving compare, hash]

    let sexp_of_t = sexp_of_t
  end

  include T
  include Comparable.Make_plain (T)
  include Hashable.Make_plain (T)
end

let%test_module _ =
  (module struct
    let check ~should_fail allowed_extensions str =
      match of_string_with_arguments ~allowed_extensions str with
      | Ok mail_from ->
        (not should_fail) && String.equal str (to_string_with_arguments mail_from)
      | Error _ -> should_fail
    ;;

    let%test _ = check ~should_fail:false [] "foo@bar.com"
    let%test _ = check ~should_fail:false [] "<>"
    let%test _ = check ~should_fail:true [] "<> <>"
    let%test _ = check ~should_fail:false [ Auth [] ] "<> AUTH=<>"
    let%test _ = check ~should_fail:false [ Auth [] ] "foo bar <foo@bar.com> AUTH=<>"
    let%test _ = check ~should_fail:false [ Auth [] ] "<foo@bar.com> AUTH=foobar"
    let%test _ = check ~should_fail:false [] "<foo@bar.com>"
    let%test _ = check ~should_fail:true [] "<foo@bar.com> AUTH=foobar"
    let%test _ = check ~should_fail:true [ Auth [] ] "<foo@bar.com> FOOBAR=foobar"
  end)
;;

module Stable = struct
  include Stable0

  module V1 = struct
    include V1_no_sexp

    include Sexpable.Of_stringable (struct
      type nonrec t = t

      let of_string s = Or_error.ok_exn (of_string s)
      let to_string t = to_string t
    end)
  end
end
OCaml

Innovation. Community. Security.