Bootstrap 4 & Phpmailer form upload file - forms

I think it's quite simple to realize but i really dont know where to start. What i would like is an option in the form where people can add an image or other file.
Ive added this in my bootstrap form:
<!--attachments-->
<div class="form-group">
<label for="attachment">Attachment</label>
<input type="file" class="form-control-file" name="attachmentFile" id="attachmentFile">
</div>
So far so good i guess. But it wont send because there has to be something added in my phpmailer / send.php file. This is the script which i use now:
<?php
require 'PHPMailerAutoload.php';
// Controleren of het formulier is verzonden dmv submit
if (isset($_POST['submitted'])) {
$errors = array(); // Initialize error array.
// Geef hier zoveel mogelijk vereiste velden voor validatie
//Add attachment
if(is_array($_FILES)) {
$mail->AddAttachment($_FILES['attachmentFile']
['tmp_name'],$_FILES['attachmentFile']['name']);
}
// Controleer naam
if (!preg_match("/^[a-zA-Z]+[a-zA-Z[:space:]]{2,}$/", $_POST['naam'])) {
$errors[] = 'Naam';
}
// Controleer adres
if (!preg_match("/^[a-zA-Z[:space:]]{1,}$/", $_POST['straat'])) {
$errors[] = 'Adres';
}
// Controleer huisnummer
if (!preg_match("/^[0-9]{1,4}$/", $_POST['huisnummer'])) {
$errors[] = 'Huisnummer';
}
// Controleer postcode
if (!preg_match("/^[0-9]{4}$/", $_POST['postcode'])) {
$errors[] = 'Postcode (Cijfers)';
}
// Controleer postcode letters
if (!preg_match("/^[a-zA-Z]{2}$/", $_POST['letters'])) {
$errors[] = 'Postcode (Letters)';
}
// Controleer woonplaats
if (!preg_match("/^[a-zA-Z]+[a-zA-Z[:space:]]{2,}$/", $_POST['woonplaats'])) {
$errors[] = 'Woonplaats';
}
// Controleer Kengetal
if (!preg_match("/^[0]{1}[0-9]{1,3}$/", $_POST['kengetal'])) {
$errors[] = 'Kengetal';
}
// Controleer telefoonnummer
if (!preg_match("/^[0-9]{6,8}$/", $_POST['telefoon'])) {
$errors[] = 'Telefoonnummer';
}
// Controleer e-mail adres
if (!preg_match("/^([a-zA-Z0-9])+([\.a-zA-Z0-9_-])*#([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-]+)*\.([a-zA-Z]{2,})$/", $_POST['email'])) {
$errors[] = 'E-mail adres';
}
// Controleer tekstvak
if (empty($_POST['bericht'])) {
$errors[] = 'Bericht';
}
if (empty($errors)) {
// Voer hier de gegevens in
$mailFrom = "myEmail";
$mailTo = "myEmail";
$senderNaam = $_POST['naam'];
$senderEmail = $_POST['email'];
$subject = 'mySubject';
$okMessage = '<p>blablabla</p>';
$errorMessage = '<p>blablabla</p>';
$emailText .= "Naam: " . $_POST['titel']." ". $_POST['naam']. "\n";
$emailText .= "Bedrijfsnaam: " . $_POST['bedrijfsnaam']. "\n";
$emailText .= "Adres: " . $_POST['straat']." ". $_POST['huisnummer']." ". $_POST['toevoeging']. "\n";
$emailText .= "Postcode: " . $_POST['postcode']." ". $_POST['letters']. "\n";
$emailText .= "Woonplaats: " . $_POST['woonplaats']. "\n";
$emailText .= "Telefoonnummer: " . $_POST['kengetal']." ". $_POST['telefoon']. "\n";
$emailText .= "E-mailadres: " . $_POST['email']. "\n";
$emailText .= "Bericht: " . $_POST['bericht']. "\n";
$mail = new PHPMailer;
$mail->CharSet = 'UTF-8';
$mail->isSMTP(); // Set mailer to use SMTP
$mail->Host = 'SMTP SERVER'; // Specify main and backup SMTP servers
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = 'User'; // SMTP username
$mail->Password = 'Pass'; // SMTP password
$mail->SMTPSecure = 'ssl'; // Enable TLS encryption, `ssl` also accepted
$mail->Port = 465; // TCP port to connect to
$mail->Sender = $mailFrom;
$mail->SetFrom($senderEmail, $senderNaam);
$mail->AddReplyTo($senderEmail, $senderNaam);
$mail->Subject = $subject;
$mail->MsgHTML($emailText);
$mail->AddAddress($mailTo, $mailTo);
$mail->addAttachment($uploadfile, 'My uploaded file'); **// ADDED THIS HERE**
$mail->isHTML(true); // Set email format to HTML
$mail->Subject = $subject;
$mail->Body = "<table>
<tr><td style='padding-left: 10px; padding-right: 10px; background: #eee;'>Naam:</td><td style='padding-left: 10px; font-weight: bold;'>".$_POST['titel']." ".$_POST['naam']."</td></tr>
<tr><td style='padding-left: 10px; padding-right: 10px; background: #eee;'>Bedrijfsnaam:</td><td style='padding-left: 10px; font-weight: bold;'>".$_POST['bedrijfsnaam']."</td></tr>
<tr><td style='padding-left: 10px; padding-right: 10px; background: #eee;'>Adres:</td><td style='padding-left: 10px; font-weight: bold;'>".$_POST['straat']." ".$_POST['huisnummer']." ".$_POST['toevoeging']."</td></tr>
<tr><td style='padding-left: 10px; padding-right: 10px; background: #eee;'>Postcode:</td><td style='padding-left: 10px; font-weight: bold;'>".$_POST['postcode']." ".$_POST['letters']."</td></tr>
<tr><td style='padding-left: 10px; padding-right: 10px; background: #eee;'>Woonplaats:</td><td style='padding-left: 10px; font-weight: bold;'>".$_POST['woonplaats']."</td></tr>
<tr><td style='padding-left: 10px; padding-right: 10px; background: #eee;'>Telefoonnummer:</td><td style='padding-left: 10px; font-weight: bold;'>".$_POST['kengetal']." ".$_POST['telefoon']."</td></tr>
<tr><td style='padding-left: 10px; padding-right: 10px; background: #eee;'>E-mailadres:</td><td style='padding-left: 10px; font-weight: bold;'>".$_POST['email']."</td></tr>
<tr><td style='padding-left: 10px; padding-right: 10px; background: #eee;'>Bericht:</td><td style='padding-left: 10px; font-weight: bold;'>".$_POST['bericht']."</td></tr>
</table>";
$mail->AltBody = $emailText;
if(!$mail->send()) {
$responseArray = array('type' => 'danger', 'message' => $errorMessage);
} else {
$responseArray = array('type' => 'success', 'message' => $okMessage);
}
}
if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
$encoded = json_encode($responseArray);
header('Content-Type: application/json');
echo $encoded;
} else {
echo $responseArray['message'];
}
}
?>
Also added this to <form> enctype="multipart/form-data"
Edit #2: I also have a contact.js file with this:
data: $(this).serialize(),
I changed it in this:
data: new FormData(this),
Because i read somewhere that this could be the problem, but it didnt make sense.

Alright, the form is sending with attachments! There is only one little thing i hope someone can help me with that.. more about this later on. First the code.
In contact.js - I had to change data: $(this).serialize(), into data: new FormData(this),
$(function () {
$('#contact-form').validator();
$('#contact-form').on('submit', function (e) {
if (!e.isDefaultPrevented()) {
var url = "send.php";
$.ajax({
type: "POST",
url: url,
data: new FormData(this),
cache : false,
contentType : false,
processData : false,
success: function (data)
{
var messageAlert = 'alert-' + data.type;
var messageText = data.message;
var alertBox = '<div class="alert ' + messageAlert + ' alert-dismissable"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>' + messageText + '</div>';
if (messageAlert && messageText) {
$('#contact-form').find('.messages').html(alertBox);
$('#contact-form')[0].reset(); //Remove this line if form should not reset after submit
$('body, html').animate({scrollTop:$('#contact-form').offset().top}, 'fast'); //Remove this line if form should not scroll to top of the form after submit
}
}
});
return false;
}
})
});
Myform.html - 2 things: this enctype="multipart/form-data" in <form>, and this
<!--attachments-->
<div class="form-group">
<label for="attachment">Attachment</label>
<input type="file" class="form-control-file" name="attachmentFile" id="attachmentFile">
</div>
somewhere you want in the form.
Finally put this in your phpmailer file:
//Add attachment
if(is_array($_FILES)) {
$mail->AddAttachment($_FILES['attachmentFile']['tmp_name'],$_FILES['attachmentFile']['name']);
}
I did it below $mail->AddAddress($mailTo, $mailTo);
So far how to fix this. There is still one problem left i refer to in the beginning.
Without data: new FormData(this), I still get my okMessage (with markup) when i hit send and the form stays at the same page.
With data: new FormData(this), it goes to a new page and just give black on white plain text (without markup).
So its like FormData is overruling something. Hope someone can help me out with this.
EDIT: Seems i have fixed this too. Place this..
cache : false,
contentType : false,
processData : false,
..below data: new FormData(this),

Related

Multiple file upload form that sends files directly to Google Drive

I'm currently trying to develop a web form that uses HTML so that users can visit this webpage and drag and drop thousands of photos. After providing an email address, these photos would be directly sent to one of our Google Drive accounts inside a subfolder of the user's email address and the time of submission.
I've played around with this code, but nowhere did I find a place for me to connect my Google Drive account.
<body>
<div id="formcontainer">
<label for="myForm">Facilities Project Database Attachment Uploader:</label>
<br><br>
<form id="myForm">
<label for="myForm">Project Details:</label>
<div>
<input type="text" name="zone" placeholder="Zone:">
</div>
<div>
<input type="text" name="building" placeholder="Building(s):">
</div>
<div>
<input type="text" name="propertyAddress" placeholder="Property Address:">
</div>
<div>
<label for="fileText">Project Description:</label>
<TEXTAREA name="projectDescription"
placeholder="Describe your attachment(s) here:"
style ="width:400px; height:200px;"
></TEXTAREA>
</div>
<br>
<label for="attachType">Choose Attachment Type:</label>
<br>
<select name="attachType">
<option value="Pictures Only">Picture(s)</option>
<option value="Proposals Only">Proposal(s)</option>
<option value="Pictures & Proposals">All</option>
</select>
<br>
<label for="myFile">Upload Attachment(s):</label>
<br>
<input type="file" name="filename" id="myFile" multiple>
<input type="button" value="Submit" onclick="iteratorFileUpload()">
</form>
</div>
<div id="output"></div>
<div id="progressbar">
<div class="progress-label"></div>
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<script>
var numUploads = {};
numUploads.done = 0;
numUploads.total = 0;
// Upload the files into a folder in drive
// This is set to send them all to one folder (specificed in the .gs file)
function iteratorFileUpload() {
var allFiles = document.getElementById('myFile').files;
if (allFiles.length == 0) {
alert('No file selected!');
} else {
//Show Progress Bar
numUploads.total = allFiles.length;
$('#progressbar').progressbar({
value : false
});//.append("<div class='caption'>37%</div>");
$(".progress-label").html('Preparing files for upload');
// Send each file at a time
for (var i = 0; i < allFiles.length; i++) {
console.log(i);
sendFileToDrive(allFiles[i]);
}
}
}
function sendFileToDrive(file) {
var reader = new FileReader();
reader.onload = function (e) {
var content = reader.result;
console.log('Sending ' + file.name);
var currFolder = 'Something';
google.script.run.withSuccessHandler(updateProgressbar).uploadFileToDrive(content, file.name, currFolder);
}
reader.readAsDataURL(file);
}
function updateProgressbar( idUpdate ){
console.log('Received: ' + idUpdate);
numUploads.done++;
var porc = Math.ceil((numUploads.done / numUploads.total)*100);
$("#progressbar").progressbar({value: porc });
$(".progress-label").text(numUploads.done +'/'+ numUploads.total);
if( numUploads.done == numUploads.total ){
//uploadsFinished();
numUploads.done = 0;
};
}
</script>
<script>
function fileUploaded(status) {
document.getElementById('myForm').style.display = 'none';
document.getElementById('output').innerHTML = status;
}
</script>
<style>
body {
max-width: 400px;
padding: 20px;
margin: auto;
}
input {
display: inline-block;
width: 100%;
padding: 5px 0px 5px 5px;
margin-bottom: 10px;
-webkit-box-sizing: border-box;
‌​ -moz-box-sizing: border-box;
box-sizing: border-box;
}
select {
margin: 5px 0px 15px 0px;
}
input[type="submit"] {
width: auto !important;
display: block !important;
}
input[type="file"] {
padding: 5px 0px 15px 0px !important;
}
#progressbar{
width: 100%;
text-align: center;
overflow: hidden;
position: relative;
vertical-align: middle;
}
.progress-label {
float: left;
margin-top: 5px;
font-weight: bold;
text-shadow: 1px 1px 0 #fff;
width: 100%;
height: 100%;
position: absolute;
vertical-align: middle;
}
</style>
</body>
Source: Uploading Multiple Files to Google Drive with Google App Script

Error with Google Places Address Autocomplete

Implemented this on our site about a month ago and it was working perfectly. Today, suddenly, I am getting this error on all pages that have the auto complete. I created a blank page with nothing but the example code copy pasted from Google's Docs, and I still get the error. Yet on Google's site, the example works.
The error is:
ReferenceError: V is not defined
...,function(a,b){V("places_impl",N(this,function(){this.Sa.getDetails(a,b)}))});G....
Here is the code, straight from Google:
<!DOCTYPE html>
<html>
<head>
<title>Place Autocomplete Address Form</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<style>
html, body, #map-canvas {
height: 100%;
margin: 0px;
padding: 0px
}
</style>
<link type="text/css" rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500">
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=places"></script>
<script>
// This example displays an address form, using the autocomplete feature
// of the Google Places API to help users fill in the information.
var placeSearch, autocomplete;
var componentForm = {
street_number: 'short_name',
route: 'long_name',
locality: 'long_name',
administrative_area_level_1: 'short_name',
country: 'long_name',
postal_code: 'short_name'
};
function initialize() {
// Create the autocomplete object, restricting the search
// to geographical location types.
autocomplete = new google.maps.places.Autocomplete(
/** #type {HTMLInputElement} */(document.getElementById('autocomplete')),
{ types: ['geocode'] });
// When the user selects an address from the dropdown,
// populate the address fields in the form.
google.maps.event.addListener(autocomplete, 'place_changed', function() {
fillInAddress();
});
}
// [START region_fillform]
function fillInAddress() {
// Get the place details from the autocomplete object.
var place = autocomplete.getPlace();
for (var component in componentForm) {
document.getElementById(component).value = '';
document.getElementById(component).disabled = false;
}
// Get each component of the address from the place details
// and fill the corresponding field on the form.
for (var i = 0; i < place.address_components.length; i++) {
var addressType = place.address_components[i].types[0];
if (componentForm[addressType]) {
var val = place.address_components[i][componentForm[addressType]];
document.getElementById(addressType).value = val;
}
}
}
// [END region_fillform]
// [START region_geolocation]
// Bias the autocomplete object to the user's geographical location,
// as supplied by the browser's 'navigator.geolocation' object.
function geolocate() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var geolocation = new google.maps.LatLng(
position.coords.latitude, position.coords.longitude);
autocomplete.setBounds(new google.maps.LatLngBounds(geolocation,
geolocation));
});
}
}
// [END region_geolocation]
</script>
<style>
#locationField, #controls {
position: relative;
width: 480px;
}
#autocomplete {
position: absolute;
top: 0px;
left: 0px;
width: 99%;
}
.label {
text-align: right;
font-weight: bold;
width: 100px;
color: #303030;
}
#address {
border: 1px solid #000090;
background-color: #f0f0ff;
width: 480px;
padding-right: 2px;
}
#address td {
font-size: 10pt;
}
.field {
width: 99%;
}
.slimField {
width: 80px;
}
.wideField {
width: 200px;
}
#locationField {
height: 20px;
margin-bottom: 2px;
}
</style>
</head>
<body onload="initialize()">
<div id="locationField">
<input id="autocomplete" placeholder="Enter your address"
onFocus="geolocate()" type="text"></input>
</div>
<table id="address">
<tr>
<td class="label">Street address</td>
<td class="slimField"><input class="field" id="street_number"
disabled="true"></input></td>
<td class="wideField" colspan="2"><input class="field" id="route"
disabled="true"></input></td>
</tr>
<tr>
<td class="label">City</td>
<td class="wideField" colspan="3"><input class="field" id="locality"
disabled="true"></input></td>
</tr>
<tr>
<td class="label">State</td>
<td class="slimField"><input class="field"
id="administrative_area_level_1" disabled="true"></input></td>
<td class="label">Zip code</td>
<td class="wideField"><input class="field" id="postal_code"
disabled="true"></input></td>
</tr>
<tr>
<td class="label">Country</td>
<td class="wideField" colspan="3"><input class="field"
id="country" disabled="true"></input></td>
</tr>
</table>
</body>
</html>
On Google's example page, there is an error relating to a variable "Tk", but it the example still works. Whatever this V is, it is killing all my code. Any help?
Though you haven't mentioned which browser you are using and whether you use Firebug, here's what worked for me:
Initially, I thought Google updated their Maps JS which introduced this bug. However, after further digging around and testing in other browsers, I finally realised that this issue is caused by Firebug 2.0. Firebug got automatically updated to v2.0 on my computer, thus resulting in the error. Downgrading Firebug resolves the issue.

How do I get a current facebook access_token when accessing group events with graph api?

I have this code for accessing and displaying Facebook events from a Facebook Group. If you use a current access_token, this works but the access_tokens are only valid for an hour or so. What code do I need to add to programatically get a current access_token each time the page loads?
I have looked at the facebook advice and it puts my page into a permanant loop.
<?php
header ('Content-type: text/html; charset=utf-8');
$limit = 5;
$group_id = '68663437095';
$url1 = 'https://graph.facebook.com/'.$group_id;
$des = json_decode(file_get_contents($url1));
$url2 = "https://graph.facebook.com/68663437095/events?access_token=CAACEdEose0cBAORQs8KFqo6Fw1ZA78alt8CgH3pyKgEVWdbsxWmBhjwVqOOSqst51fb1ZCHK0Dtz8CmTDCZByqoJMoaXcEU6qjN4IO1JWExSwuHzVRmNU5JEkzpdcSuhPd8StyYSObAhXU4DKngmnHtvF018wZAmsg8GEFXNatcZAZBBMbJmsUOvwSOa7DubIZD";
$data = json_decode(file_get_contents($url2));
?>
<style type="text/css">
.wrapper {
width:200px;
border:1px solid #ccc;
font-family: "lucida grande",tahoma,verdana,arial,sans-serif;
background-color: black;
float:left;
}
.top {
margin:5px;
border-bottom:2px solid #e1e1e1;
float: left;
width:290px;
}
.single {
margin:5px;
border-bottom:1px dashed #e1e1e1;
float:left;
}
.img {
float:left;
width:60px;
text-align:center;
margin:5px 5px 5px 0px;
border-right:1px dashed #e1e1e1;
}
.text {
width:220px;
float:left;
font-size:10px;
}
a {
text-decoration: none;
color: #3b5998;
}
</style>
<div style="width: 250px; padding-bottom:15px;"><br/>
<div style="width: 190x; margin-left:15px;">
<a target="_parent" style="font-size:40px;" href="http://www.facebook.com/groups/fumcbixby/"> <?=$des->name?></a>
<div style="width:100%; margin: 5px">
<?=$des->description?>
</div>
</div><br/>
<?
$counter = 0;
foreach($data->data as $d) {
if($counter==$limit)
break;
?>
<div style="width: auto; background-color:white; margin-left:15px; margin-bottom:15px; padding:5px">
<div style="float: left; width:120px;">
<img src="https://graph.facebook.com/<?= $d->id?>/picture">
</div>
<div>
<h2>Name <?= $d->name?></h2>
<h3>Location <?= $d->location?></h3>
<p>Start<?= date('F j, Y H:i',strtotime($d->start_time))?></p>
<p>End<?= date('F j, Y H:i',strtotime($d->end_time))?></p>
Visit Event
</div>
</div>
<?
$counter++;
}
?>
</div>
Get Extended Access Token which will be valid for 60 days
https://graph.facebook.com/oauth/access_token?
client_id=APP_ID&
client_secret=APP_SECRET&
grant_type=fb_exchange_token&
fb_exchange_token=EXISTING_ACCESS_TOKEN
Put APP_ID, APP_SECRET & EXISTING_ACCESS_TOKEN in the above url & make a HTTP request.
HTTP request will return JSON Array. Then you can easily parse Extended Access Token
Have a look at this question....
How to renew/extend facebook access tokens with PHP?

Google App Script to trigger email

I'm trying to get an email to fire alerting me if a column in a Google Sheet =X.
I've tried using the notification system using using the EQ operator to turn on when a cell equals X, this changes a cell and the notification system is supposed to send an email right away. It's not working that way, the email never fires.
I'm think I need a script that would fire an email if a cell =X which would be nice because I could customize the email so it made more sense. (i.e. "The conference room your event is being held has reached capacity, you should remove it from the reservation form")
I am new to Google Scripts and could use a little help creating the email trigger if cell =X script.
Thanks,
Dave
You would need to add a script to run onEdit.
function onEdit() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("NameOfYourSheet");
var currentValue = sheet.getRange("A5").getValue();
if (currentValue == (whateverValueYoureLookingFor)) {
MailApp.sendEmail("youremail#domain.com", "ALERT: The cell in the sheet is equal to X!", "The message body that you want to send.");
}
}
function testSchemas() {
var htmlout = HtmlService.createTemplateFromFile('data').evaluate().getContent();
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('All Exams Tracker');
var range = sheet.getDataRange();
var values = range.getValues();
var last_row = sheet.getLastRow();
var today = new Date()
for (var i =3 ;i < last_row;i++) {
var temp = values[i][4];
var e_date = new Date(temp);
if ((( e_date - today)/(1000*60*60*24)) < 10 && e_date > today){
var cond = "done" }
break; }
Logger.log(cond);
if (cond == "done"){
MailAppv.sendEmail({
to: '*************************************************************',
subject: 'Exam Coming Next Week',
htmlBody: htmlout,
});
}}
This will html file data (given below) when triggered.
<html>
<head>
<style>
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
th, td {
padding: 5px;
}
</style>
</head>
<table style = "border: 1px solid black; border-style: collapse;">
<? var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('All Exams Tracker');
var range = sheet.getDataRange();
var values = range.getValues();
var last_row = sheet.getLastRow();
var today = new Date();?>
<tr style="border: 1px solid black; padding: 10px;">
<th style="border: 1px solid black; padding: 10px;">Exam Name</th>
<th style="border: 1px solid black; padding: 10px;">Exam Date</th>
<th style="border: 1px solid black; padding: 10px;">Priority</th>
<th style="border: 1px solid black; padding: 10px;">College Predictor Status</th>
<th style="border: 1px solid black; padding: 10px;">Rank Predictor Status</th>
</tr>
<? for (var i =3 ;i < last_row;i++) {
var temp = values[i][4];
var e_date = new Date(temp);
if ((( e_date - today)/(1000*60*60*24)) < 10 && e_date > today) {
if (values[i][12] != ""){
var col_status = "Live"}
else
if (values[i][11] != ""){
col_status = "Uploaded and Tested"}
else
if (values[i][10] != ""){
col_status = "Data Processed"}
else
if (values[i][9] != ""){
col_status = "Template Ready"}
else
col_status = "Not initiated yet"
if (values[i][19] != ""){
var rank_status = "Live"}
else
if (values[i][18] != ""){
rank_status = "Uploaded and Tested"}
else
if (values[i][17] != ""){
rank_status = "Data Processed"}
else
rank_status = "Not Initiated yet"
?>
<tr>
<td style="border: 1px solid black; padding: 10px;"><?= values[i][2]?></td>
<td style="border: 1px solid black; padding: 10px;"><?= values[i][4]?></td>
<td style="border: 1px solid black; padding: 10px;"><?= values[i][8]?></td>
<td style="border: 1px solid black; padding: 10px;"><?= col_status?></td>
<td style="border: 1px solid black; padding: 10px;"><?= rank_status?></td>
</tr>
<? } }?>
</table>
<br><br>
<p>Click Here For More Details</p>
</html>

drupal_mail() HTML

I'm trying to send out a simple email with some HTML, drupal_mail() is sending out the email, but all HTML seems to be removed.
$body = '<div style="width: 600px; margin: 0px auto">';
$body .= '<img align="center" src="' . $url . '" style="max-width: 600px; height: auto; margin: 0px auto">';
$body .= '<p style="margin: 30px 0px 0px 0px; line-height: 18px">' . nl2br($message) . '</p>';
$body .= '</div>';
params = array(
'subject' => 'An e-card from HKUST',
'body' => $body
);
if(drupal_mail('ecard', 'ecard_email', $single_email, language_default(), $params, $yourEmail, TRUE)) {
echo 'Send';
}
function ecard_mail($key, &$message, $params) {
$headers = array(
'MIME-Version' => '1.0',
'Content-Type' => 'text/html; charset=UTF-8; format=flowed',
'Content-Transfer-Encoding' => '8Bit',
'X-Mailer' => 'Drupal'
);
foreach($headers as $key => $value) {
$message['headers'][$key] = $value;
};
$message['subject'] = $params['subject'];
$message['body'][] = $params['body'];
}
Am I still missing something here?
EDIT: When I check the email in gmail, I can see this:
X-PHP-Originating-Script: 381:system.mail.inc
MIME-Version: 1.0
Content-Type: text/html; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8Bit
X-Mailer: Drupal
So I guess the HTML is filtered by drupal before sending