├── .gitignore ├── .npmignore ├── README.md ├── bin └── cli.js ├── index.js ├── package.json ├── src ├── cli.js ├── ksend.js └── util.js └── temp └── zip.temp /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .idea/ 3 | src/config.json -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | src/config.json -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ksend 2 | ===== 3 | 4 | 命令行推送个人文档到kindle。 5 | 6 | **使用指南** 7 | 8 | 1. 安装 9 | 10 | npm install -g ksend 11 | 12 | 2. 设置默认发送邮箱,格式: 邮箱地址:密码 13 | 14 | ksend --from yourname@qq.com:yourpassword 15 | 16 | 3. 推送,如下示例,推送 a.pdf 至 hanan@kindle.cn 这个kindle接收邮箱: 17 | 18 | ksend -m hanan@kindle.cn a.pdf 19 | 20 | 以上命令,参数 -m 表示接收邮箱。自此,完成推送。 21 | 22 | 如果脚得每次都要敲 -m 接收邮箱 麻烦,可以设置默认接收邮箱: 23 | 24 | ksend --to hanan@kindle.cn 25 | 26 | 这样,以后只需要如下命令即可推送: 27 | 28 | ksend a.pdf 29 | 30 | 也可以同时推送多个文档: 31 | 32 | ksend a.pdf b.pdf ../img/photo.jpg /Users/hanan/book/ooxx.txt 33 | 34 | 查看帮助: 35 | 36 | ksend --help 37 | 38 | ps: 记得把发送邮箱添加到您的kindle已认可的发件人电子邮箱列表哦 -------------------------------------------------------------------------------- /bin/cli.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var fs = require('fs'); 4 | var path =require('path'); 5 | 6 | var config = path.join(__dirname, '../src/config.json'); 7 | if (!fs.existsSync(config)) { 8 | fs.writeFileSync(config, JSON.stringify({})); 9 | } 10 | require('./../src/cli')(); 11 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by an.han on 15/1/1. 3 | */ 4 | module.exports = require('./src/ksend'); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ksend", 3 | "version": "0.0.6", 4 | "description": "命令行推送个人文档到kindle。", 5 | "main": "index.js", 6 | "bin": "bin/cli.js", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "https://github.com/hanan198501/ksend.git" 13 | }, 14 | "keywords": [ 15 | "kindle", 16 | "ksend" 17 | ], 18 | "author": "韩安", 19 | "license": "ISC", 20 | "bugs": { 21 | "url": "https://github.com/hanan198501/ksend/issues" 22 | }, 23 | "homepage": "https://github.com/hanan198501/ksend", 24 | "dependencies": { 25 | "archiver": "^0.13.0", 26 | "nodemailer": "^1.3.0", 27 | "nodemailer-smtp-transport": "^0.1.13", 28 | "optimist": "^0.6.1" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/cli.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by an.han on 15/1/1. 3 | */ 4 | 5 | var fs = require('fs'); 6 | var path = require('path'); 7 | var optimist = require('optimist'); 8 | var Ksend = require('./ksend'); 9 | var util = require('./util'); 10 | 11 | var ksend = new Ksend(); 12 | var pwd = process.env.PWD || process.cwd(); 13 | var argv = optimist.argv; 14 | 15 | module.exports = function () { 16 | 17 | // 如果有设置项,设置之 18 | if (argv.from || argv.to) { 19 | 20 | // 设置默认发送邮箱 21 | if (argv.from) { 22 | if (!util.checkFromInput(argv.from)) { 23 | return console.error('输入有误,邮箱地址和密码请用“:”分隔,如 abc@qq.com:123456 。'); 24 | } 25 | var from = argv.from.split(':')[0]; 26 | var password = argv.from.split(':')[1]; 27 | setConfig({from: from, password: password}); 28 | console.log('设置默认发送邮箱成功,请将 ' + from + ' 添加至你的kindle已认可的发件人电子邮箱列表。'); 29 | } 30 | 31 | //设置默认kindle接收邮箱 32 | if (argv.to) { 33 | if (!util.checkToInput(argv.to)) { 34 | return console.error('邮件地址格式错误。'); 35 | } 36 | setConfig({to: argv.to}); 37 | console.log('设置默认kindle接收邮箱成功。'); 38 | } 39 | } 40 | 41 | // 显示帮助信息 42 | else if (argv.help || !argv._.length) { 43 | showHelp(); 44 | } 45 | 46 | // 推送至kindle 47 | if (argv._.length) { 48 | var to = argv.m || ksend.config.to; 49 | var attachments = []; 50 | var nameStr = []; 51 | 52 | if (!ksend.config.from) { 53 | return console.error('默认发送邮箱未设置,请用 --from 设置。'); 54 | } 55 | 56 | if (!to) { 57 | return console.error('kindle接收邮箱未指定,请用 -m 指定,或用 --to 设置默认接收邮箱。'); 58 | } 59 | 60 | argv._.forEach(function (item) { 61 | var filename = util.getFileName(item); 62 | nameStr.push(' ' + filename) 63 | attachments.push({ 64 | filename: filename, 65 | path: path.resolve(pwd, item) 66 | }); 67 | }); 68 | 69 | console.log('正在推送:\n' + nameStr.join('\n') + '\n共' + attachments.length + '个文档到 ' + to + ' ,请耐心等待...'); 70 | 71 | util.zip(attachments, function (error, zipAttachments) { 72 | if (error) { 73 | return console.error('压缩文件失败:\n', error); 74 | } 75 | ksend.send({ 76 | to: to, 77 | subject: 'convert', 78 | attachments: zipAttachments 79 | }, function (error, info) { 80 | removeTempFile(zipAttachments); 81 | if (error) { 82 | console.error('推送失败:\n', error); 83 | } 84 | else { 85 | console.log('恭喜!推送成功。'); 86 | } 87 | }); 88 | }); 89 | } 90 | } 91 | 92 | function setConfig(obj) { 93 | for (var i in obj) { 94 | util.setConfig(i, obj[i]); 95 | ksend.setConfig(i, obj[i]); 96 | } 97 | } 98 | 99 | function removeTempFile(files) { 100 | files.forEach(function (file) { 101 | fs.unlinkSync(file.path); 102 | }) 103 | } 104 | 105 | function showHelp() { 106 | console.log( 107 | 'Usage: ksend [-m mail] file 推送文档 \n' + 108 | ' or: ksend [--from mail:password] 设置默认发送邮箱 \n' + 109 | ' or: ksend [--to mail] 设置默认接收邮箱 \n' + 110 | '\n' + 111 | 'Options: \n' + 112 | ' --from 设置默认发送邮箱和密码,邮箱地址和密码请用“:”分隔,格式如 abc@qq.com:123456 \n' + 113 | ' --to 设置默认kindle接收邮箱\n' + 114 | ' -m 设置当前kindle接收邮箱,推送时如果不带此参数,则使用默认接收邮箱\n' + 115 | ' --help 显示帮助信息' 116 | ); 117 | } 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /src/ksend.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by an.han on 15/1/1. 3 | */ 4 | 5 | var nodemailer = require('nodemailer'); 6 | var smtpTransport = require('nodemailer-smtp-transport'); 7 | var util = require('./util'); 8 | 9 | 10 | var Ksend = function (config) { 11 | this.config = config || util.getConfig() || {}; 12 | } 13 | 14 | Ksend.prototype.parseFrom = function () { 15 | var fromArr = (this.config.from || '').split('@'); 16 | return { 17 | host: 'smtp.' + fromArr[1], 18 | user: this.config.from, 19 | password: this.config.password 20 | } 21 | } 22 | 23 | 24 | Ksend.prototype.setConfig = function (key, value) { 25 | this.config[key] = value; 26 | return this; 27 | } 28 | 29 | 30 | Ksend.prototype.getSmtpOpton = function () { 31 | var from = this.parseFrom(); 32 | var smtpOption = { 33 | host: from.host, 34 | auth: { 35 | user: from.user, 36 | pass: from.password 37 | } 38 | } 39 | 40 | switch (from.host){ 41 | case 'smtp.qq.com': 42 | smtpOption.port = 465; 43 | smtpOption.secure = true; 44 | break; 45 | default : 46 | break; 47 | } 48 | 49 | return smtpOption; 50 | } 51 | 52 | 53 | Ksend.prototype.send = function (mail, callback) { 54 | var self = this; 55 | var smtpOption = self.getSmtpOpton(); 56 | var transport = nodemailer.createTransport(smtpTransport(smtpOption)); 57 | transport.sendMail(util.extend({from: self.config.from, to: self.config.to}, mail), callback); 58 | return self; 59 | } 60 | 61 | module.exports = Ksend; -------------------------------------------------------------------------------- /src/util.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by an.han on 15/1/1. 3 | */ 4 | 5 | var fs = require('fs'); 6 | var path = require('path'); 7 | var archiver = require('archiver'); 8 | 9 | var configPath = path.join(__dirname, './config.json'); 10 | 11 | var regFrom = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,5}):\S+$/; 12 | var regTo = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,5})$/; 13 | 14 | var util = { 15 | 16 | getConfig: function () { 17 | return JSON.parse(fs.readFileSync(configPath)); 18 | }, 19 | 20 | setConfig: function (key, value) { 21 | var config = JSON.parse(fs.readFileSync(configPath)); 22 | config[key] = value; 23 | fs.writeFileSync(configPath, JSON.stringify(config)); 24 | }, 25 | 26 | extend: function (a, b) { 27 | for (var i in b) { 28 | if (typeof b[i] !== 'undefined') { 29 | a[i] = b[i]; 30 | } 31 | } 32 | return a; 33 | }, 34 | 35 | checkFromInput: function (val) { 36 | return regFrom.test(val); 37 | }, 38 | 39 | checkToInput: function (val) { 40 | return regTo.test(val); 41 | }, 42 | 43 | getFileName: function (file) { 44 | var arr = file.split('/'); 45 | return arr[arr.length - 1]; 46 | }, 47 | 48 | parseTime: function (time) { 49 | time = time || new Date(); 50 | var y = time.getFullYear(); 51 | var M = time.getMonth() + 1; 52 | var d = time.getDate(); 53 | var h = time.getHours(); 54 | var m = time.getMinutes(); 55 | var s = time.getSeconds(); 56 | M = M > 9 ? M : '0' + M; 57 | d = d > 9 ? d : '0' + d; 58 | h = h > 9 ? h : '0' + h; 59 | m = m > 9 ? m : '0' + m; 60 | s = s > 9 ? s : '0' + s; 61 | return '' + y + M + d + h + m + s; 62 | }, 63 | 64 | zip: function (attachments, callback) { 65 | var filename = 'ksend' + util.parseTime() + '.zip'; 66 | var filePath = path.resolve(__dirname, '../temp', filename); 67 | var output = fs.createWriteStream(filePath); 68 | var archive = archiver('zip'); 69 | 70 | output.on('close', function() { 71 | callback(null, [{ 72 | filename: filename, 73 | path: filePath 74 | }]) 75 | }); 76 | 77 | archive.on('error', function(error) { 78 | callback(error) 79 | }); 80 | 81 | archive.pipe(output); 82 | 83 | attachments.forEach(function (atta) { 84 | archive.append(fs.createReadStream(atta.path), {name: atta.filename}); 85 | }); 86 | 87 | archive.finalize(); 88 | } 89 | } 90 | 91 | module.exports = util; -------------------------------------------------------------------------------- /temp/zip.temp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/annnhan/ksend/1877f4f342e733dd69685d83021605c4f723b94d/temp/zip.temp --------------------------------------------------------------------------------