+(defcustom notmuch-mua-compose-in 'current-window
+ "Where to create the mail buffer used to compose a new message.
+Possible values are `current-window' (default), `new-window' and
+`new-frame'. If set to `current-window', the mail buffer will be
+displayed in the current window, so the old buffer will be
+restored when the mail buffer is killed. If set to `new-window'
+or `new-frame', the mail buffer will be displayed in a new
+window/frame that will be destroyed when the buffer is killed.
+You may want to customize `message-kill-buffer-on-exit'
+accordingly."
+ :group 'notmuch-send
+ :type '(choice (const :tag "Compose in the current window" current-window)
+ (const :tag "Compose mail in a new window" new-window)
+ (const :tag "Compose mail in a new frame" new-frame)))
+
+(defcustom notmuch-mua-user-agent-function nil
+ "Function used to generate a `User-Agent:' string.
+If this is `nil' then no `User-Agent:' will be generated."
+ :type '(choice (const :tag "No user agent string" nil)
+ (const :tag "Full" notmuch-mua-user-agent-full)
+ (const :tag "Notmuch" notmuch-mua-user-agent-notmuch)
+ (const :tag "Emacs" notmuch-mua-user-agent-emacs)
+ (function :tag "Custom user agent function"
+ :value notmuch-mua-user-agent-full))
+ :group 'notmuch-send)
+
+(defcustom notmuch-mua-hidden-headers nil
+ "Headers that are added to the `message-mode' hidden headers list."
+ :type '(repeat string)
+ :group 'notmuch-send)
+
+(defcustom notmuch-identities nil
+ "Identities that can be used as the From: address when composing a new message.
+
+If this variable is left unset, then a list will be constructed from the
+name and addresses configured in the notmuch configuration file."
+ :type '(repeat string)
+ :group 'notmuch-send)
+
+(defcustom notmuch-always-prompt-for-sender nil
+ "Always prompt for the From: address when composing or forwarding a message.
+
+This is not taken into account when replying to a message, because in that case
+the From: header is already filled in by notmuch."
+ :type 'boolean
+ :group 'notmuch-send)
+
+(defgroup notmuch-reply nil
+ "Replying to messages in notmuch."
+ :group 'notmuch)
+
+(defcustom notmuch-mua-cite-function 'message-cite-original
+ "Function for citing an original message.
+
+Predefined functions include `message-cite-original' and
+`message-cite-original-without-signature'. Note that these
+functions use `mail-citation-hook' if that is non-nil."
+ :type '(radio (function-item message-cite-original)
+ (function-item message-cite-original-without-signature)
+ (function-item sc-cite-original)
+ (function :tag "Other"))
+ :link '(custom-manual "(message)Insertion Variables")
+ :group 'notmuch-reply)
+
+(defcustom notmuch-mua-reply-insert-header-p-function
+ 'notmuch-show-reply-insert-header-p-never
+ "Function to decide which parts get a header when replying.
+
+This function specifies which parts of a mime message with
+multiple parts get a header."
+ :type '(radio (const :tag "No part headers"
+ notmuch-show-reply-insert-header-p-never)
+ (const :tag "All except multipart/* and hidden parts"
+ notmuch-show-reply-insert-header-p-trimmed)
+ (const :tag "Only for included text parts"
+ notmuch-show-reply-insert-header-p-minimal)
+ (const :tag "Exactly as in show view"
+ notmuch-show-insert-header-p)
+ (function :tag "Other"))
+ :group 'notmuch-reply)
+
+(defcustom notmuch-mua-attachment-regexp
+ "\\b\\(attache\?ment\\|attached\\|attach\\|pi[èe]ce\s+jointe?\\)\\b"
+ "Message body text indicating that an attachment is expected.
+
+This is not used unless `notmuch-mua-attachment-check' is added
+to `notmuch-mua-send-hook'."
+ :type 'regexp
+ :group 'notmuch-send)
+
+;;; Various functions
+
+(defun notmuch-mua-attachment-check ()
+ "Signal an error an attachement is expected but missing.
+
+Signal an error if the message text indicates that an attachment
+is expected but no MML referencing an attachment is found.
+
+Typically this is added to `notmuch-mua-send-hook'."
+ (when (and
+ ;; When the message mentions attachment...
+ (save-excursion
+ (message-goto-body)
+ ;; Limit search from reaching other possible parts of the message
+ (let ((search-limit (search-forward "\n<#" nil t)))
+ (message-goto-body)
+ (cl-loop while (re-search-forward notmuch-mua-attachment-regexp
+ search-limit t)
+ ;; For every instance of the "attachment" string
+ ;; found, examine the text properties. If the text
+ ;; has either a `face' or `syntax-table' property
+ ;; then it is quoted text and should *not* cause the
+ ;; user to be asked about a missing attachment.
+ if (let ((props (text-properties-at (match-beginning 0))))
+ (not (or (memq 'syntax-table props)
+ (memq 'face props))))
+ return t
+ finally return nil)))
+ ;; ...but doesn't have a part with a filename...
+ (save-excursion
+ (message-goto-body)
+ (not (re-search-forward "^<#part [^>]*filename=" nil t)))
+ ;; ...and that's not okay...
+ (not (y-or-n-p "Attachment mentioned, but no attachment - is that okay?")))
+ ;; ...signal an error.
+ (error "Missing attachment")))
+
+(defun notmuch-mua-get-switch-function ()
+ "Get a switch function according to `notmuch-mua-compose-in'."
+ (pcase notmuch-mua-compose-in
+ ('current-window 'switch-to-buffer)
+ ('new-window 'switch-to-buffer-other-window)
+ ('new-frame 'switch-to-buffer-other-frame)
+ (_ (error "Invalid value for `notmuch-mua-compose-in'"))))
+
+(defun notmuch-mua-maybe-set-window-dedicated ()
+ "Set the selected window as dedicated according to `notmuch-mua-compose-in'."
+ (when (or (eq notmuch-mua-compose-in 'new-frame)
+ (eq notmuch-mua-compose-in 'new-window))
+ (set-window-dedicated-p (selected-window) t)))