Email
2019-01-10
介绍
iCal 历史
-
Versit 联盟阶段
1995 年,为了解决不同设备、不同程序之间交互个人数据(联系人、日程)困难的问题,苹果、AT&T、IBM 等公司组成 Versit 联盟,旨在制定个人信息交换(PDI)的开放标准。
后来,该组织设计了以下两个标准:
- vCard,用于交换名片信息,包括姓名、地址、电话号码、邮箱地址等。
- vCalender,用于交换日历信息,如日程、会议等。
基本格式都是这样,只是里面的字段定义不同:
BEGIN:type
key1:value1
key2:value2
END:type
-
IMC 联盟阶段
1996 年,为了促进上面两项标准的推广,Versit 联盟将相关格式所有权移交给了互联网邮件联盟(Internet Mail Consortium,IMC)。
PS:IMC 可能是 Versit 联盟成员拉拢更多公司组成的一个更大的联盟。
PS:2002 年,IMC 组织关门。
IMC closed down in 2002.
-
IETF 阶段
1998 年,IMC 将两个标准提交给 Internet Engineering Task Force (IETF) 标准化。
PS:vCalendar 经过 IETF 标准化之后改名 iCalendar 了。
支持情况
经过测试,至少 QQ 和 网易邮箱的 WebMail 都提供了日程的支持。
Thunderbird 只能通过日历 App 打开附件 (ics 文件) 的方式添加日程。
效果

原理
在邮件中插入了一个 text/calendar 类型的附件:
Content-Type: text/calendar; charset=utf-8; method=REQUEST;
name=ATT1547083200618.ics
Content-Transfer-Encoding: base64
Content-Disposition: inline; filename="ATT1547083200618.ics"
解析出来这样一个 iCal 文件:
BEGIN:VCALENDAR
PRODID:-//Netease//WebMail
VERSION:2.0
METHOD:REQUEST
BEGIN:VEVENT
SUMMARY:日程:上午十点的面试
LOCATION:小会议室
DTSTART:20190110T013000Z
DTEND:20190110T023000Z
UID:11c27eb7-adab-4549-8aea-efadcec7bb6c
SEQUENCE:0
STATUS:CONFIRMED
ORGANIZER;CN=张三:mailto:zhangsan@example.com
ATTENDEE:mailto:lisi@example.com
END:VEVENT
END:VCALENDAR
回复
这个回复就各异了,没有同意的格式。
QQ 邮件只会有一个 自动回复: xxxx,不知道是接受还是拒绝。
QQ 企业邮件会有详细的信息,附带了原日程,并有一句话:xxx 已经接受你的邀请: 日程:xxx。
参考资料与拓展阅读
WebDev 缓存
2019-01-06
Apache,Nginx 都有缓存功能,再加上 Redis 做动态数据的缓存,再加上 CDN,所以我还没有用过专门的缓存服务。
但是这些服务真是大名鼎鼎,即便不用,我也可以先列出来做个简单的了解。
Git
2019-01-03
命令
usage: git submodule [--quiet] [--cached]
or: git submodule [--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--] <repository> [<path>]
or: git submodule [--quiet] status [--cached] [--recursive] [--] [<path>...]
or: git submodule [--quiet] init [--] [<path>...]
or: git submodule [--quiet] deinit [-f|--force] (--all| [--] <path>...)
or: git submodule [--quiet] update [--init [--filter=<filter-spec>]] [--remote] [-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--[no-]recommend-shallow] [--reference <repository>] [--recursive] [--[no-]single-branch] [--] [<path>...]
or: git submodule [--quiet] set-branch (--default|--branch <branch>) [--] <path>
or: git submodule [--quiet] set-url [--] <path> <newurl>
or: git submodule [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]
or: git submodule [--quiet] foreach [--recursive] <command>
or: git submodule [--quiet] sync [--recursive] [--] [<path>...]
or: git submodule [--quiet] absorbgitdirs [--] [<path>...]
相关文件
-
.gitmodules
[submodule "<moduleName>"]
path = <moduleDir>
url = <repoAddr>
-
.git/config 中有相近的 section:
[submodule "<moduleName>"]
active = true
url = <repoAddr>
-
.git 目录在 .git/modules/<moduleName>
克隆
参考:https://stackoverflow.com/questions/3796927/how-to-git-clone-including-submodules
git clone --recurse-submodules -j8 github.com:shouce/shouce.git # 2.13+
git clone --recursive -j8 github.com:shouce/shouce.git # 1.6.5+
-j 表示子模块并发操作,每次 n 个子模块。
针对更老的版本或者以存在的库:
git clone github.com:shouce/shouce.git
cd shouce
git submodule update --init --recursive
发现一个 clone 参数 --[no-]shallow-submodules,可以使每个子模块仓库的克隆 deepth 为 1,应该是用得上的。
已存在的项目
可能是克隆的时候没有克隆子仓库,也可能是后面添加进来的子仓库。
$ git submodule init
Submodule '<moduleName>' (<repoAddr>) registered for path '<moduleDir>'
$ git submodule update
Cloning into '<moduleFullPath>'...
Submodule path '<moduleDir>': checked out '<commitID>'
或者二合一:
git submodule update --init --recursive
后面有更新就进入子模块 git pull。
添加子模块
git submodule add -b dev --name devtools gitee.com:catroll/devtools tools/dev
# [submodule "devtools"]
# path = tools/dev
# url = gitee.com:catroll/devtools
# branch = dev
删除子模块
$ git submodule deinit <moduleDir>
Cleared directory '<moduleDir>'
Submodule '<moduleName>' (<remoteAddr>) unregistered for path '<moduleDir>'
作用:
- 清空子模块目录下的所有文件
- 去掉 .git/config 子模块配置
这个操作之后:git status 没有任何变化,.gitmodule 还保留着。
然后:
- 修改 .gitmodules
- 删除子模块目录
- 提交变更
- 推送到远程仓库
ORM 软件开发
2019-01-01
:) 本文正在编辑中,暂时不提供浏览...
Python Pipenv Virtualenv Crontab
2018-12-20
部署
# curl: (35) SSL connect error
# StackOverflow: You are using a very old version of curl.
# yum upgrade curl
# 安装 pyenv
curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash
# 环境变量
PYENV_ROOT="$HOME/.pyenv"
PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
# 可用版本列表
pyenv install -l
# 使用国内 Python 镜像,相当于给 pyenv 加速
wget https://mirrors.sohu.com/python/3.6.7/Python-3.6.7.tar.xz -P ~/.pyenv/cache/
# 安装(优先使用缓存目录中的文件,会检查缓存校验码是否正确)
pyenv install 3.6.7
运行方式
假定:
- 项目路径:
/path/to/project/
- 定时任务命令:
python main.py
crontab 配置
早上 01:15 执行某某定时任务:
15 1 * * * /bin/bash /path/to/project/cron.sh
脚本 cron.sh
pyenv + pip 模式
#!/bin/bash
# 环境变量
PYENV_ROOT="$HOME/.pyenv"
PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
cd /path/to/project/
# 创建并激活虚拟环境,安装依赖
# $PYENV_ROOT/versions/3.6.7/envs/tasks/
pyenv virtualenv 3.6.7 tasks
if [ $? -ne 0 ]; then
pyenv activate tasks
pip install -r requirements.txt
else
pyenv activate tasks
fi
# 运行脚本
python main.py
pyenv + pipenv 模式
#!/bin/bash
# 环境变量
PYENV_ROOT="$HOME/.pyenv"
PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
cd /path/to/project/
# 选择 Python 版本
pyenv local 3.6.7
pip show pipenv > /dev/null
if [ $? -ne 0 ]; then
# 安装 pipenv
pip install pipenv
# 创建虚拟环境,安装依赖
pipenv install
fi
# 运行脚本
pipenv run python main.py
WebDev SSO OpenLDAP CAS Auth
2018-12-16
这套方案名气比较大,了解看看。
WebDev SSO Auth
2018-12-15
:) 本文正在编辑中,暂时不提供浏览...
开发者
2018-12-14
方便资产统计
Python HTTP/2
2018-12-13
HTTP/2 都出来三年半了,还没有一个好用的 Python 客户端库,真是的。
开发工具 VirtualBox 虚拟化
2018-12-13
之前只有一个 50G 存储,后来磁盘空间总不够,就把占空间比较大的 Projects 目录(用户主目录下)移出来,弄了一个独立的 50G 盘。
过了段时间,又隔三差五提醒我空间不够了,baobab 清理了,可以删除的东西一删,多出几 GB 来。
但是看结果,还是扩容一下,一了百了。