title: SendGrid Attachments Are Empty or Corrupt Using API (VBA)
body: <p>This seems to be a constant issue with the SendGrid Web API and emailing attachments. I've found many, many posts across the web all of whom are having this same issue... but none of them seem to be answered with a solution. SendGrid's own canned response is use one of their libraries... but the question remains how do you attach files when you are using a language that does not have a library.</p>
  
  <p>I've tried contacting SendGrid support myself on this issue... even offered to pay for support to get an answer but they thought I was asking for a "code review" which I wasn't. The question is simply this: What is needed to upload attachments to the SendGrid Web API.</p>
  
  <p>I previously used to just provide the file location within the suggested API format as seen here: <a href="http://www.access-programmers.co.uk/forums/showthread.php?t=278421&amp;page=2" rel="nofollow">Previous Example of Posting to SendGrid Using VBA</a> and this seemed to work fine for a while for myself and several others... but lately something has changed. Providing a simple file path no longer seems to work. So what do I need to do now? Should I encode the file? If so what encoding should I use base64? Any help in this would be greatly appreciated by me and many others!!</p>
  
  <p>Here is my base64 attempt but it is having the same issue as my previous file path attempts i.e. the attachment shows in the email... but it can not be opened.</p>
  
  <pre><code>Private Sub SendEmail()
      Dim rs As DAO.Recordset
      Dim SQL As String
      Dim byteData() As Byte
      Dim xmlhttp As Object
      Dim eTo As String
      Dim eFrom As String
      Dim eBody As String
      Dim eSubject As String
      Dim eToName As String
      Dim HttpReq As String
      Dim ePass As String
      Dim eUser As String
      Dim strXML As String
      Dim strAttachments As String
      Dim strBase64 As String
  
  
  
      eSubject = Me.txtSubject
      eBody = Me.txtMessage
      eFrom = SenderEmail
      eUser = SendGridUser
      ePass = SendGridPass
  
      ' If Groups List/ Else Contacts List
      If Me.chkGroups &lt;&gt; 0 Then
          SQL = "SELECT * FROM qryContactsInSelectedGroups WHERE ContactType = 'Email'"
      Else
          SQL = "SELECT * FROM qrySelectedContacts WHERE ContactType = 'Email'"
      End If
      Set rs = CurrentDb.OpenRecordset(SQL, dbOpenDynaset, dbSeeChanges)
  
      If Not (rs.EOF And rs.BOF) Then
          rs.MoveFirst
          Do Until rs.EOF = True
              eTo = rs.Fields("ContactValue").Value
              eToName = rs.Fields("FirstName").Value &amp; " " &amp; rs.Fields("LastName").Value
  
                ' Set the Server URL to the form input
              HttpReq = "https://api.sendgrid.com/api/mail.send.xml?" _
              &amp; "api_user=" &amp; eUser _
              &amp; "&amp;api_key=" &amp; ePass _
              &amp; "&amp;to=" &amp; eTo _
              &amp; "&amp;toname=" &amp; eToName _
              &amp; "&amp;subject=" &amp; eSubject _
              &amp; "&amp;text=" &amp; eBody _
              &amp; "&amp;from=" &amp; eFrom _
              &amp; GetAttachments()
              ' files[file1.jpg]=file1.jpg&amp;files[file2.pdf]=file2.pdf
              Set xmlhttp = CreateObject("MSXML2.XMLHTTP")
             ' adoStream.Position = 0
              xmlhttp.Open "POST", HttpReq, False
              xmlhttp.send
  
              byteData = xmlhttp.responseBody
  
              Set xmlhttp = Nothing
              strXML = StrConv(byteData, vbUnicode)
              Call EmailResponse(strXML, rs.Fields("ContactID").Value)
              Debug.Print strXML
              rs.MoveNext
          Loop
      End If
      Set rs = Nothing
  End Sub
  
      Private Function GetAttachments() As String
      Dim rs As DAO.Recordset
      Dim SQL As String
      Dim currentAttachment As String
      Dim strAttachments As String
      Dim Encoded64 As String
  
      SQL = "SELECT * FROM tblMessageAttachments WHERE [MessageID] = " &amp; MessageID
      Set rs = CurrentDb.OpenRecordset(SQL, dbOpenDynaset, dbSeeChanges)
  
      If Not (rs.EOF And rs.BOF) Then
          rs.MoveFirst
          Do Until rs.EOF = True
              ' Set Current Attachment
              currentAttachment = rs.Fields("AttachmentLocation").Value &amp; rs.Fields("AttachmentName").Value
              Encoded64 = EncodeFile(currentAttachment)
              strAttachments = strAttachments &amp; "&amp;files" &amp; Chr(91) &amp; rs.Fields("AttachmentName").Value &amp; Chr(93) &amp; "=" &amp; Encoded64 'currentAttachment
              'strAttachments = strAttachments &amp; Encoded64
             ' Debug.Print strAttachments
  
              rs.MoveNext
          Loop
          Debug.Print strAttachments
          GetAttachments = strAttachments
      End If
  
  End Function
  
  Private Function EncodeFile(text As String) As String
    Dim arrData() As Byte
    arrData = StrConv(text, vbFromUnicode)
  
    Dim objXML As MSXML2.DOMDocument
    Dim objNode As MSXML2.IXMLDOMElement
  
    Set objXML = New MSXML2.DOMDocument
    Set objNode = objXML.createElement("b64")
  
    objNode.DataType = "bin.base64"
    objNode.nodeTypedValue = arrData
    EncodeFile = Replace(objNode.text, vbLf, "")
  
    Set objNode = Nothing
    Set objXML = Nothing
  
  End Function
  </code></pre>