     end
   end
 
+  def new({:data, data}, opts) do
+    %{struct!(__MODULE__, opts) | data: data}
+  end
+
   def new(path, opts) do
-    filename = opts[:filename] || Path.basename(path)
-    content_type = opts[:content_type] || MIME.from_path(path)
-    type = opts[:type] || :attachment
-    headers = opts[:headers] || []
+    attachment = struct!(__MODULE__, opts)
 
-    %__MODULE__{
-      path: path,
-      filename: filename,
-      content_type: content_type,
-      type: type,
-      headers: headers
+    %{
+      attachment
+      | path: path,
+        filename: attachment.filename || Path.basename(path),
+        content_type: attachment.content_type || MIME.from_path(path)
     }
   end
 

  Struct representing an attachment in an email.
  """

  defstruct [:filename, :content_type, :path, :type, :headers, :data]

  @type t :: %__MODULE__{
    filename: String.t,
    content_type: String.t,
    path: String.t | nil,
    data: binary | nil,
    type: :inline | :attachment,
    headers: [{String.t, String.t}],
  }

  @doc ~S"""
  Creates a new Attachment

      Attachment.new(params["file"], type: "inline") # Where params["file"] is a %Plug.Upload

  """
  @spec new(binary | struct, Keyword.t() | map) :: %__MODULE__{}
  def new(path, opts \\ [])

  if Code.ensure_loaded?(Plug) do
