package email_message
E-mail message parser
Install
Dune Dependency
Authors
Maintainers
Sources
v0.17.0.tar.gz
sha256=3aa5c85da8530c277cf9e72e18861b235b3b872f08c87f118c04478433320ebb
doc/src/email_message.kernel/email_content.ml.html
Source file email_content.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 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
open! Core module Multipart : sig type t = private { boundary : Boundary.t ; prologue : Bigstring_shared.t option ; epilogue : Bigstring_shared.t option ; parts : Email.t list ; container_headers : Headers.t } [@@deriving sexp_of] val create_unsafe : boundary:Boundary.t -> ?prologue:Bigstring_shared.t -> ?epilogue:Bigstring_shared.t -> Email.t list -> container_headers:Headers.t -> t val create : ?boundary:Boundary.t -> ?prologue:Bigstring_shared.t -> ?epilogue:Bigstring_shared.t -> ?container_headers:Headers.t -> Email.t list -> t val set : t -> ?boundary:Boundary.t -> ?prologue:Bigstring_shared.t option -> ?epilogue:Bigstring_shared.t option -> ?parts:Email.t list -> ?container_headers:Headers.t -> unit -> t include String_monoidable.S with type t := t end = struct type t = { boundary : Boundary.t ; prologue : Bigstring_shared.t option ; epilogue : Bigstring_shared.t option ; parts : Email.t list ; container_headers : Headers.t } [@@deriving sexp_of] let create_unsafe ~boundary ?prologue ?epilogue parts ~container_headers = { boundary; prologue; epilogue; parts; container_headers } ;; let create ?boundary ?prologue ?epilogue ?(container_headers = Headers.empty) parts = let boundary = Boundary.generate_non_conflicting_boundary ?prologue ~parts:(List.map parts ~f:Email.to_string_monoid) ?epilogue (Option.value_map boundary ~default:Boundary.Generator.default ~f:Boundary.Generator.from_existing_boundary) in create_unsafe ~boundary ?prologue ?epilogue parts ~container_headers ;; let set t ?(boundary = t.boundary) ?(prologue = t.prologue) ?(epilogue = t.epilogue) ?(parts = t.parts) ?(container_headers = t.container_headers) () = create ~boundary ?prologue ?epilogue ~container_headers parts ;; let to_string_monoid t = Boundary.join_without_checking_for_conflicts ?prologue:t.prologue ~parts:(List.map t.parts ~f:Email.to_string_monoid) ?epilogue:t.epilogue t.boundary ;; end type t = | Multipart of Multipart.t | Message of Email.t | Data of Octet_stream.t [@@deriving sexp_of] let rec ~boundary ~container_headers bstr = let open Or_error.Let_syntax in let prologue, parts, epilogue = Boundary.split boundary bstr in let%map parts = List.map parts ~f:(fun part -> Or_error.tag (Or_error.try_with (fun () -> Email.of_bigstring (Bigstring_shared.to_bigstring part))) ~tag:(sprintf "failed part:\n%s" (Bigstring_shared.to_string part))) |> Or_error.all in Multipart.create_unsafe ~boundary ?prologue ?epilogue ~container_headers parts and ~headers ?container_headers bstr = let open Or_error.Let_syntax in let parent_media_type = Option.bind container_headers ~f:Media_type.from_headers in let media_type = Option.value (Media_type.from_headers headers) ~default:(Media_type.default ?parent:parent_media_type ()) in let encoding = Octet_stream.Encoding.of_headers_or_default headers in let octet_stream = Octet_stream.of_bigstring_shared ~encoding bstr in let decode octet_stream = match Octet_stream.decode octet_stream with | None -> Or_error.error "Unknown message encoding" encoding Octet_stream.Encoding.sexp_of_t | Some decoded_bstr -> Ok decoded_bstr in match Media_type.multipart_boundary media_type with | Some boundary -> (* According to Wikipedia, the content-transfer-encoding of a multipart type must always be "7bit", "8bit" or "binary" to avoid the complications that would be posed by multiple levels of decoding. In this case this decode call is free. *) let%bind decoded_bstr = decode octet_stream in let%bind multipart = multipart_of_bigstring_shared ~boundary ~container_headers:headers decoded_bstr in Ok (Multipart multipart) | None -> if Media_type.is_message_rfc822 media_type then ( let%bind decoded_bstr = decode octet_stream in let%bind email = Or_error.try_with (fun () -> Email.of_bigstring (Bigstring_shared.to_bigstring decoded_bstr)) in Ok (Message email)) else Ok (Data octet_stream) and parse ?container_headers email = content_of_bigstring_shared ?container_headers ~headers:(Email.headers email) (Email.raw_content email |> Email_raw_content.to_bigstring_shared) ;; let to_string_monoid = function | Multipart multipart -> Multipart.to_string_monoid multipart | Message message -> Email.to_string_monoid message | Data octet_stream -> Octet_stream.encoded_contents octet_stream |> Bigstring_shared.to_string_monoid ;; let t = to_string_monoid t |> String_monoid.to_bigstring |> Bigstring_shared.of_bigstring ;; let to_raw_content t = to_bigstring_shared t |> Email_raw_content.of_bigstring_shared let rec multipart_map_data ~on_unparsable_content mp ~f = Multipart.set mp ~parts:(List.map mp.Multipart.parts ~f:(map_data ~on_unparsable_content ~f)) () and content_map_data ~on_unparsable_content t ~f = match t with | Multipart t -> Multipart (multipart_map_data ~on_unparsable_content t ~f) | Message message -> Message (map_data ~on_unparsable_content message ~f) | Data data -> Data (f data) and map_data ~on_unparsable_content email ~f = match parse email with | Ok content -> let content = content_map_data content ~on_unparsable_content ~f in Email.set_raw_content email (to_bigstring_shared content |> Email_raw_content.of_bigstring_shared) | Error e -> (match on_unparsable_content with | `Skip -> email | `Raise -> raise_s [%message "[map_data] has unparsable content" (e : Error.t)]) ;; let map_data ?(on_unparsable_content = `Skip) email ~f = map_data ~on_unparsable_content email ~f ;; let to_email ~headers t = let headers = let media_type = match t with | Multipart mp -> (match Media_type.from_headers headers with | None -> Some (Media_type.create_multipart "related" ~boundary:mp.boundary) | Some media_type -> Some (Media_type.set_multipart_boundary media_type mp.boundary)) | _ -> None in match media_type with | None -> headers | Some media_type -> Media_type.set_headers headers media_type in Email.create ~headers ~raw_content:(to_bigstring_shared t |> Email_raw_content.of_bigstring_shared) ;; let set_content email t = to_email ~headers:(Email.headers email) t
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>