diff --git a/.gitignore b/.gitignore index 9021ead..4ecebc5 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,6 @@ assets/ templates/ lists/ vendor/ +*~ +filespread.ini +*.sum \ No newline at end of file diff --git a/README.md b/README.md index 5359431..6a2dede 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ npm install composer install ``` -Make sure you have gulp installed on your system and run +Make sure you have gulp and the Dart SDK installed on your system and run ``` gulp sass @@ -24,6 +24,10 @@ gulp sass gulp coffee ``` +``` +gulp dart +``` + Create the folders `templates`, `assets` and `lists` and make sure that the server can write in these folders. Finally remove the example files. @@ -34,4 +38,9 @@ Filespread is licensed under the MIT license. # Contributing -Please refer to the [Contributing Guidlines](https://mmk2410.org/contribute/) +1. Fork it +2. Create a feature branch with a meaningful name (`git checkout -b my-new-feature`) +3. Add yourself to the CONTRIBUTORS file +4. Commit your changes (`git commit -am 'Add some feature'`) +5. Push to your branch (`git push origin my-new-feature`) +6. Create a new pull request diff --git a/filespread.ini b/filespread.ini index 8f74fab..f1cac2c 100644 --- a/filespread.ini +++ b/filespread.ini @@ -10,3 +10,6 @@ timezone = "UTC" email = "example@example.com" ; name which is given as a sender name name = "John" +; reply address +; if not set, the values above will be used +reply = "" \ No newline at end of file diff --git a/gulpfile.coffee b/gulpfile.coffee index de480a1..3ae8d4d 100755 --- a/gulpfile.coffee +++ b/gulpfile.coffee @@ -4,6 +4,7 @@ gulp = require 'gulp' coffee = require 'gulp-coffee' sass = require 'gulp-sass' +dart = require 'gulp-dart' gulp.task 'coffee', -> gulp.src './res/js/*.coffee' @@ -15,6 +16,15 @@ gulp.task 'sass', -> .pipe sass() .pipe gulp.dest './res/css/' +gulp.task 'dart', -> + gulp.src './res/dart/*.dart' + .pipe dart { + "dest": "./res/dart/", + "minify": "true", + } + .pipe gulp.dest './res/dart/' + gulp.task 'default', -> gulp.watch './res/js/*.coffee', ['coffee'] gulp.watch './res/css/*.sass', ['sass'] + gulp.watch './res/dart/*.dart', ['dart'] diff --git a/index.html b/index.html index 3150783..39cfabd 100755 --- a/index.html +++ b/index.html @@ -68,6 +68,7 @@

Change the text of the email if you want.

Title:

Text:

+

Send without file

Filename:

@@ -171,5 +172,6 @@ + diff --git a/package.json b/package.json index 0dd2fac..d92b6ed 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "devDependencies": { "gulp": "^3.9.1", "gulp-coffee": "^2.3.1", + "gulp-dart": "^0.2.4", "gulp-sass": "^2.1.0", "node-sass": "^3.4.2" }, diff --git a/res/css/main.sass b/res/css/main.sass index 7b558c8..12df386 100755 --- a/res/css/main.sass +++ b/res/css/main.sass @@ -163,6 +163,12 @@ input.button .itextarea:focus @extend .itextfield +.icheckbox + margin: 0 + padding: 0 + margin-right: 10px + vertical-align: sub + /* FILESPREAD */ .edit_template @@ -180,6 +186,11 @@ input.button .remove_list display: none +#addresses + max-height: 200px + overflow-x: hidden + overflow-y: auto + /* FORM */ form margin-top: 20px diff --git a/res/dart/.gitignore b/res/dart/.gitignore new file mode 100644 index 0000000..2205f7b --- /dev/null +++ b/res/dart/.gitignore @@ -0,0 +1,23 @@ +# Files and directories created by pub +.packages +.pub/ +build/ +packages +# Remove the following pattern if you wish to check in your lock file +pubspec.lock + +# Files created by dart2js +*.dart.js +*.part.js +*.js.deps +*.js.map +*.info.json + +# Directory created by dartdoc +doc/api/ + +# JetBrains IDEs +.idea/ +*.iml +*.ipr +*.iws diff --git a/res/dart/main.dart b/res/dart/main.dart new file mode 100644 index 0000000..0881b29 --- /dev/null +++ b/res/dart/main.dart @@ -0,0 +1,83 @@ +// Copyright (c) 2016 - 2017, Marcel Kapfer (mmk2410). +// MIT License + +/// frontend code for filespread, a simple file over email spreading web app. +import 'dart:convert'; +import 'dart:html'; + +/// main method with click listners. +void main() { + // send mail listener + querySelector("#send").onClick.listen(sendMail); + + // save address list listner + querySelector("#save-addresses").onClick.listen(saveAddresses); +} + +/// function for calling the backend to send mails. +void sendMail(MouseEvent event) { + InputElement title = querySelector("#mailtitle"); + InputElement text = querySelector("#mailtext"); + InputElement filename = querySelector("#filename"); + InputElement addresslist = querySelector("#address_list"); + CheckboxInputElement nofile = querySelector("#nofile"); + + Map data = { + "title": title.value, + "body": text.value, + "filename": filename.value, + "list": addresslist.value, + "nofile": nofile.checked + }; + + String url = "res/php/sendmail.php?data=${JSON.encode(data)}"; + + HttpRequest.getString(url).then((String response) { + if (response == "0") { + window.alert("Mails successfully sent."); + } else { + window.alert("Failed to send mail."); + } + }); +} + +/// function to update the addresses list in the backend. +void saveAddresses(MouseEvent event) { + TextAreaElement addresses = querySelector("#edit-addresses"); + SelectElement list = querySelector("#edit-address-list"); + + List addressesList = new List(); + + addresses.value.split("\n").forEach((String address) { + if (address.isNotEmpty) addressesList.add(address); + }); + + Map data = {"list": list.value, "addresses": addressesList}; + + String url = "res/php/savelist.php"; + + HttpRequest.postFormData(url, {"data": JSON.encode(data)}).then((HttpRequest response) { + if (response.responseText == "0") { + window.alert("Addresses sucessfully saved."); + updateAddresses(addressesList, list.value); + } else { + window.alert("Failed to save adresses."); + } + }); +} + +/// Updated the frontend after an address change. +void updateAddresses(List addresses, String list) { + SelectElement currentList = querySelector("#address_list"); + + if (currentList.value == list) { + DivElement addressesContainer = querySelector("#addresses"); + addressesContainer.children .removeWhere((Element child) => addressesContainer.children.contains(child)); + + addresses.forEach((String address) { + ParagraphElement addressElement = new ParagraphElement(); + addressElement.text = address; + addressesContainer.children.add(addressElement); + }); + } +} diff --git a/res/js/main.coffee b/res/js/main.coffee index 46d009f..6972938 100755 --- a/res/js/main.coffee +++ b/res/js/main.coffee @@ -3,16 +3,6 @@ # MIT License main = -> - - $("#send").click -> - url = "./res/php/sendmail.php?list=" + $("#address_list").val() + - "&template=" + $("#templates_list").val() - $.get url, (data) -> - if data is "0" - alert "Mail sent!" - else - alert "Sending mail failed!" - updateAddressLists() updateTemplateLists() @@ -115,20 +105,6 @@ main = -> $("#edit-addresses").val(text) $(".edit_address").fadeIn() - $("#save-addresses").click -> - data = - list: $("#edit-address-list").val() - addresses: $("#edit-addresses").val().split '\n' - if data.addresses[data.addresses.length - 1] is "" - data.addresses.pop() - $.get "./res/php/savelist.php", {"data": data}, (data) -> - if data == "0" - alert "List sucessfully changed!" - if data.list is $("#address_list") - updateAddresss data.list - else - alert "Error while saving the edit." - $("#create-list").click -> filename = $("#create-list-name").val() if filename.substring((filename.length - 4)) isnt ".txt" diff --git a/res/php/savelist.php b/res/php/savelist.php index a2f9b56..8f223e5 100644 --- a/res/php/savelist.php +++ b/res/php/savelist.php @@ -1,8 +1,8 @@ + * + * @param $ini an configuration map. + */ +function main($ini) { -$addresses = file($list); -$content = file($template); + $data = json_decode($_GET["data"], true); -$email = new PHPMailer; + $list = "../../lists/" . $data["list"]; + $addresses = file($list); -$email->setFrom($ini["email"], $ini["name"]); -$email->Subject = parseSubject($content); -$email->Body = parseText($content); + $content = $data["body"]; -foreach ($addresses as $address) { - $email->AddAddress($address); -} + $title = $data["title"]; -$file_to_attach = '../../assets/file.bin'; -$filename = parseFilename($content); + $filename = $data["filename"]; -$email->AddAttachment($file_to_attach, $filename); + $nofile = $data["nofile"]; -if (!$email->Send()) { - echo "-1"; - echo $email->ErrorInfo; -} else { - echo "0"; -} - -function parseSubject($content) { - return substr($content[0], 7); -} - -function parseFilename($content) { - return substr($content[1], 10); -} - -function parseText($content) { - $text = substr($content[2], 6); - for ($i = 3; $i < count($content); $i++) { - $text = $text . $content[$i]; + if ($nofile) { + $filename = ""; } - return $text; + + foreach ($addresses as $address) { + if (sendMail($title, $content, $filename, $address, $ini) != 0) { + print "-1"; + exit; + } + } + + print "0"; + } + +/** + * function for sending the mail. + * + * @author Marcel Kapfer + * + * @param $title the subject of the mail. + * @param $content the text of the mail. + * @param $address the receiver of the mail. + * @param $ini an configuration map. + */ +function sendMail($title, $content, $filename, $address, $ini) { + + $mail = new PHPMailer; + $mail->CharSet = 'UTF-8'; + + $mail->setFrom($ini["email"], $ini["name"]); + $mail->Subject = $title; + $mail->Body = $content; + + $mail->addAddress($address); + + if (isset($ini["reply"])) { + $mail->addReplyTo($ini["reply"]); + } + + if (!empty($filename)) { + $mail->AddAttachment("../../assets/file.bin", $filename); + } + + if (!$mail->Send()) { + return -1; + } else { + return 0; + } + +} + +main($ini);