当前位置: 首页 > 编程日记 > 正文

使用 acl 库编写发送邮件的客户端程序

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

邮件做为最早和最广的互联应网用之一,已经与人们的生活息息相关。我们虽然经常使用 Outlook Express/Outlook/Foxmail 等邮件客户端发送邮件,但并不关心发送过程的细节。如果您是一名程序员,则偶尔需要自己写一个小程序来实现发送邮件的目的,本文将会介绍如何使用 acl 里的 smtp_client 模块快速实现一个邮件发送的客户端程序。下面是发送邮件一个简单流程:

220 inc365.com ESMTP mail for UNIX (mail1.0)

ehlo localhost

250-inc365.com

250-PIPELINING

250-SIZE 51200000

250-VRFY

250-ETRN

250-AUTH LOGIN

250-AUTH=LOGIN

250-ENHANCEDSTATUSCODES

250-8BITMIME

250 DSN

auth login

334 dXNlcm5hbWU6

emhlbmdzaHV4aW5AaW5jMzY1LmNvbQ==

334 cGFzc3dvcmQ6

YWFhYWFh

235 2.0.0 Authentication successful

mail from: aaaa@sss.ssss.ssss

250 2.1.0 Ok

rcpt to: zhengshuxin@inc365.com

250 2.1.5 Ok

data

354 End data with <CR><LF>.<CR><LF>

subject: hello world

from: aaaa@sss.ssss.ssss

to: zhengshuxin@inc365.com


hello!

.

250 2.0.0 Ok: queued

quit

221 2.0.0 Bye

其中,黄色部分为邮件客户端的命令请求过程,红色部分为邮件服务器的命令响应过程。该交互过程并不复杂,其实客户端发送的命令主要有:

1)ehlo/helo: 问候服务器命令

2)auth login: SMTP 身份认证命令

3)mail from: 发送发件人邮箱地址命令

4)rcpt to: 发送收件人邮箱地址命令

5)data: 发送开始发邮件数据的命令,以行为单位发送数据,所发送数据需要经过编码处理(采用 base64/qp 等编码)转为可打印的字符串,当发送一行数据中只有 . 时则表示邮件数据完毕

6)quit: 退出发送过程命令

邮件发送过程虽然简单,但每次都重新写发送过程未免罗嗦,所以在 acl 项目的 lib_protocol 库中提供了 smtp_client 模块用来发送邮件。在 lib_protocol/include/smtp/smtp_client.h 中提供了常用的 SMTP 发送协议的函数接口,如下所示:

/*** 远程连接 SMTP 服务器* @param addr {const char*} SMTP 服务器地址,格式:domain:port* @param timeout {int} 连接超时时间及IO读写超时时间* @param line_limit {int} SMTP 会话过程中每行的最大长度限制* @return {SMTP_CLIENT*} 连接成功返回非空值,否则返回 NULL*/
SMTP_API SMTP_CLIENT *smtp_open(const char *addr, int timeout, int line_limit);/*** 关闭由 smtp_open 打开的 SMTP 连接并释放对象* @param client {SMTP_CLIENT*} SMTP 连接对象*/
SMTP_API void smtp_close(SMTP_CLIENT *client);/*** 获得 SMTP 服务器的欢迎信息* @param client {SMTP_CLIENT*} SMTP 连接对象* @return {int} 0 表示成功(SMTP_CLIENT::smtp_code 表示返回码,*  SMTP_CLIENT::buf 存储响应内容),否则表示出错,应该关闭连接对象*/
SMTP_API int smtp_get_banner(SMTP_CLIENT *client);/*** 向 SMTP 服务器发送 HELO/EHLO 命令* @param client {SMTP_CLIENT*} SMTP 连接对象* @param name {const char*} 握手信息,一般用域名* @param ehlo {int} 非 0 时使用 EHLO,否则使用 HELO* @return {int} 0 表示成功(SMTP_CLIENT::smtp_code 表示返回码,*  SMTP_CLIENT::buf 存储响应内容),否则表示出错,应该关闭连接对象*/SMTP_API int smtp_greet(SMTP_CLIENT *client, const char* name, int ehlo);/*** 向 SMTP 服务器发送 HELO 命令* @param client {SMTP_CLIENT*} SMTP 连接对象* @param helo {const char*} 握手信息,一般用域名* @return {int} 0 表示成功(SMTP_CLIENT::smtp_code 表示返回码,*  SMTP_CLIENT::buf 存储响应内容),否则表示出错,应该关闭连接对象*/
SMTP_API int smtp_helo(SMTP_CLIENT *client, const char *helo);/*** 向 SMTP 服务器发送 EHLO 命令* @param client {SMTP_CLIENT*} SMTP 连接对象* @param ehlo {const char*} 握手信息,一般用域名* @return {int} 0 表示成功(SMTP_CLIENT::smtp_code 表示返回码,*  SMTP_CLIENT::buf 存储响应内容),否则表示出错,应该关闭连接对象*/
SMTP_API int smtp_ehlo(SMTP_CLIENT *client, const char *ehlo);/*** 向 SMTP 服务器发送验证信息* @param client {SMTP_CLIENT*} SMTP 连接对象* @param user {const char*} SMTP 邮件账号* @param pass {const char*} SMTP 邮件账号密码* @return {int} 0 表示成功(SMTP_CLIENT::smtp_code 表示返回码,*  SMTP_CLIENT::buf 存储响应内容),否则表示出错,应该关闭连接对象*/
SMTP_API int smtp_auth(SMTP_CLIENT *client, const char *user, const char *pass);/*** 向 SMTP 服务器发送 MAIL FROM 命令* @param client {SMTP_CLIENT*} SMTP 连接对象* @param from {const char*} 发送者邮箱* @return {int} 0 表示成功(SMTP_CLIENT::smtp_code 表示返回码,*  SMTP_CLIENT::buf 存储响应内容),否则表示出错,应该关闭连接对象*/
SMTP_API int smtp_mail(SMTP_CLIENT *client, const char *from);/*** 向 SMTP 服务器发送 RCPT TO 命令* @param client {SMTP_CLIENT*} SMTP 连接对象* @param to {const char*} 接收者邮箱* @return {int} 0 表示成功(SMTP_CLIENT::smtp_code 表示返回码,*  SMTP_CLIENT::buf 存储响应内容),否则表示出错,应该关闭连接对象*/
SMTP_API int smtp_rcpt(SMTP_CLIENT *client, const char *to);/*** 向 SMTP 服务器发送 DATA 命令* @param client {SMTP_CLIENT*} SMTP 连接对象* @return {int} 0 表示成功(SMTP_CLIENT::smtp_code 表示返回码,*  SMTP_CLIENT::buf 存储响应内容),否则表示出错,应该关闭连接对象*/
SMTP_API int smtp_data(SMTP_CLIENT *client);/*** 向 SMTP 服务器发送邮件体内容,可以循环调用本函数直至数据发送完毕* @param client {SMTP_CLIENT*} SMTP 连接对象* @param src {const char*} 遵守邮件 MIME 编码格式的邮件体内容* @param len {size_t} src 数据长度* @return {int} 0 表示成功(SMTP_CLIENT::smtp_code 表示返回码,*  SMTP_CLIENT::buf 存储响应内容),否则表示出错,应该关闭连接对象*/
SMTP_API int smtp_send(SMTP_CLIENT *client, const char* src, size_t len);/*** 向 SMTP 服务器发送邮件体内容,可以循环调用本函数直至数据发送完毕* @param client {SMTP_CLIENT*} SMTP 连接对象* @param fmt {const char*} 格式字符串* @param ... 变参* @return {int} 0 表示成功(SMTP_CLIENT::smtp_code 表示返回码,*  SMTP_CLIENT::buf 存储响应内容),否则表示出错,应该关闭连接对象*/
SMTP_API int smtp_printf(SMTP_CLIENT *client, const char* fmt, ...);/*** 发送完邮件内容后调用本函数告诉 SMTP 服务器邮件数据完毕* @param client {SMTP_CLIENT*} SMTP 连接对象* @return {int} 0 表示成功(SMTP_CLIENT::smtp_code 表示返回码,*  SMTP_CLIENT::buf 存储响应内容),否则表示出错,应该关闭连接对象*/
SMTP_API int smtp_data_end(SMTP_CLIENT *client);/*** 向 SMTP 服务器发送指定件路径的邮件文件* @param client {SMTP_CLIENT*} SMTP 连接对象* @param filepath {const char*} 邮件文件路径* @return {int} 0 表示成功(SMTP_CLIENT::smtp_code 表示返回码,*  SMTP_CLIENT::buf 存储响应内容),否则表示出错,应该关闭连接对象*/
SMTP_API int smtp_send_file(SMTP_CLIENT *client, const char *filepath);/*** 向 SMTP 服务器发送给定文件流的邮件内容* @param client {SMTP_CLIENT*} SMTP 连接对象* @param int {ACL_VSTREAM*} 邮件文件输入流* @return {int} 0 表示成功(SMTP_CLIENT::smtp_code 表示返回码,*  SMTP_CLIENT::buf 存储响应内容),否则表示出错,应该关闭连接对象*/
SMTP_API int smtp_send_stream(SMTP_CLIENT *client, ACL_VSTREAM *in);/*** 向 SMTP 服务器发送退出(QUIT)命令* @param client {SMTP_CLIENT*} SMTP 连接对象* @return {int} 0 表示成功(SMTP_CLIENT::smtp_code 表示返回码,*  SMTP_CLIENT::buf 存储响应内容),否则表示出错,应该关闭连接对象*/
SMTP_API int smtp_quit(SMTP_CLIENT *client);/*** 向 SMTP 服务器发送 NOOP 命令* @param client {SMTP_CLIENT*} SMTP 连接对象* @return {int} 0 表示成功(SMTP_CLIENT::smtp_code 表示返回码,*  SMTP_CLIENT::buf 存储响应内容),否则表示出错,应该关闭连接对象*/
SMTP_API int smtp_noop(SMTP_CLIENT *client);/*** 向 SMTP 服务器发送 RSET 命令* @param client {SMTP_CLIENT*} SMTP 连接对象* @return {int} 0 表示成功(SMTP_CLIENT::smtp_code 表示返回码,*  SMTP_CLIENT::buf 存储响应内容),否则表示出错,应该关闭连接对象*/
SMTP_API int smtp_rset(SMTP_CLIENT *client);

读者也许注意到每个函数前都有一个前缀:SMTP_API,这个前缀当你使用 VC 编译应用程序且选择了动态链接库时才会用到,此时需要增加条件编译开关:SMTP_DLL,以告诉VC编译器需要导出函数接口;在使用VC的静态链接方式或在UNIX下编译时,SMTP_API 仅是一个空定义而已。

灵活使用这些函数接口,您便可以轻松实现一个邮件发送客户端,现在给一个具体的实例来(该实例在 samples/smp_client/ 目录下)说明函数接口的调用过程,如下:

/* smtp_client.cpp : 定义控制台应用程序的入口点 */#include "lib_acl.h"
#include "lib_protocol.h"#ifdef WIN32
#define snprintf _snprintf
#endifstatic int smtp_sender(void)
{SMTP_CLIENT* conn;char  addr[128], line[256];acl_printf("please enter smtp server addr: ");if (acl_gets_nonl(line, sizeof(line)) == NULL){acl_puts("invalid smtp server addr");return -1;}if (strchr(line, ':') == NULL)snprintf(addr, sizeof(addr), "%s:25", line);elsesnprintf(addr, sizeof(addr), line);/* 连接 SMTP 服务器 */conn = smtp_open(addr, 60, 1024);if (conn == NULL){acl_printf("connect %s error %s\r\n", addr, acl_last_serror());return -1;}elseacl_printf("connect smtpd(%s) ok\r\n", addr);/* 从 SMTP 服务器获得欢迎信息 */if (smtp_get_banner(conn) != 0){acl_puts("get banner from server error");smtp_close(conn);return -1;}elseacl_printf(">smtpd: %s\r\n", conn->buf);/* 向 SMTP 服务器发送 EHLO/HELO 命令 */if (smtp_greet(conn, "localhost", 0) != 0){acl_printf("send ehlo cmd error: %s\r\n", conn->buf);smtp_close(conn);return -1;}elseacl_printf(">smtpd: %s\r\n", conn->buf);/* 用户是否需要进行 SMTP 身份认证 */acl_printf("Do you want to auth login? n[y|n]: ");if (acl_gets_nonl(line, sizeof(line)) == NULL){acl_puts("invalid input");smtp_close(conn);return -1;}/* 对用户身份进行 SMTP 身份认证 */else if (strcasecmp(line, "Y") == 0){char user[128], pass[128];acl_printf("Please input user account: ");if (acl_gets_nonl(user, sizeof(user)) == NULL){acl_puts("input invalid");smtp_close(conn);return -1;}acl_printf("Please input user password: ");if (acl_gets_nonl(pass, sizeof(pass)) == NULL){acl_puts("input invalid");smtp_close(conn);return -1;}/* 开始进行 SMTP 身份认证 */if (smtp_auth(conn, user, pass) != 0){acl_printf("smtp auth(%s, %s) error: %s, code: %d\r\n",user, pass, conn->buf, conn->smtp_code);smtp_close(conn);return -1;}elseacl_printf(">smtpd: %s\r\n", conn->buf);}/* 获得发件人邮箱地址 */acl_printf("please input sender's email: ");if (acl_gets_nonl(line, sizeof(line)) == NULL){acl_puts("invalid sender's email");smtp_close(conn);return -1;}/* 发送 MAIL FROM: 命令 */if (smtp_mail(conn, line) != 0){acl_printf("smtp send MAIL FROM %s error\r\n", line);smtp_close(conn);return -1;}elseacl_printf(">smtpd: %s\r\n", conn->buf);/* 发送 RCPT TO: 命令 */while (1){acl_printf("please input mail recipients: ");if (acl_gets_nonl(line, sizeof(line)) == NULL){acl_puts("invalid mail recipients");smtp_close(conn);return -1;}/* 发送 RCPT TO: 命令 */else if (smtp_rcpt(conn, line) != 0){acl_printf("send RCPT TO: %s error: %s, code: %d\r\n",line, conn->buf, conn->smtp_code);smtp_close(conn);return -1;}elseacl_printf(">smtpd: %s\r\n", conn->buf);acl_printf("Do you want to add another recipients? n[y|n]: ");if (acl_gets_nonl(line, sizeof(line)) == NULL){acl_puts("input invalid");smtp_close(conn);return -1;}else if (strcasecmp(line, "y") != 0)break;}/* 发送 DATA: 命令 */if (smtp_data(conn) != 0){acl_printf("send DATA error %s, code: %d\r\n",conn->buf, conn->smtp_code);smtp_close(conn);return -1;}elseacl_printf(">smtpd: %s\r\n", conn->buf);/* 从终端接收用户的输入的邮件内容并发往 SMTP 服务器 */acl_puts("Please enter the email data below, end with \\r\\n.\\r\\n");while (1){if (acl_gets_nonl(line, sizeof(line)) == NULL){acl_puts("readline error");smtp_close(conn);return -1;}if (strcmp(line, ".") == 0)break;if (smtp_printf(conn, "%s\r\n", line) != 0){acl_printf("send data to smtpd error, data: %s\r\n", line);smtp_close(conn);return -1;}}/* 发送 \r\n.\r\n 表示邮件数据发送完毕 */if (smtp_data_end(conn) != 0){acl_printf("send . error: %s, code: %d\r\n",conn->buf, conn->smtp_code);smtp_close(conn);return -1;}elseacl_printf(">smtpd: %s\r\n", conn->buf);/* 发送 QUIT 命令 */if (smtp_quit(conn) != 0){acl_printf("smtp QUIT error: %s\r\n", conn->buf);smtp_close(conn);return -1;}elseacl_printf(">smtpd: %s\r\n", conn->buf);smtp_close(conn);return 0;
}int main(void)
{int   ret;#ifdef WIN32acl_init();
#endifwhile (1){char line[128];ret = smtp_sender();if (ret == -1)break;acl_printf("Do you want to send another email? n[y|n]: ");if (acl_gets_nonl(line, sizeof(line)) == NULL){acl_puts("invalid input");break;}else if (strcasecmp(line, "y") != 0)break;}#ifdef WIN32acl_vstream_printf("enter any key to exit\r\n");acl_vstream_getc(ACL_VSTREAM_IN);
#endifreturn ret;
}

无论使用 VC2003 编译还是在LINUX下用GCC编译,运行可执行程序,均会得到如下结果:

please enter smtp server addr: mail.inc365.com:25

connect smtpd(mail.inc365.com:25) ok

>smtpd: 220 inc365.com ESMTP mail for UNIX (mail1.0)

>smtpd: 250 inc365.com

Do you want to auth login? n[y|n]:

please input sender's email: zsxxsz@sina.com

>smtpd: 250 2.1.0 Ok

please input mail recipients: zhengshuxin@inc365.com

>smtpd: 250 2.1.5 Ok

Do you want to add another recipients? n[y|n]:

>smtpd: 354 End data with <CR><LF>.<CR><LF>

Please enter the email data below, end with \r\n.\r\n

subject: hello world

from: zsxxsz@sina.com

to: zhengshuxin@inc365.com

hello world

.

>smtpd: 250 2.0.0 Ok: queued

>smtpd: 221 2.0.0 Bye

acl 库下载: https://sourceforge.net/projects/acl/

acl svn 地址:svn://svn.code.sf.net/p/acl/code/

个人微博:http://weibo.com/zsxxsz

转载于:https://my.oschina.net/u/568966/blog/309543

相关文章:

Unreal Engine+Houdini创造程序性游戏场景视频教程

Unreal EngineHoudini创造程序性游戏场景视频教程 大小解压后&#xff1a;27.4G 持续时间14小时30分 包括项目文件 1920X1080 高清视频 程序游戏环境——虚幻引擎和Houdini 信息: 云桥网络 平台获取教程 导言: 欢迎来到虚幻引擎4和Houdini的程序游戏环境课程&#xff0…

清理内存clear

清理内存clear&#xff1a; package com.android.cleanprocesstool;import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import a…

linux mv 环境变量,linux环境变量,cp,mv命令,more,less,cat,tail,head,的使用...

linux环境变量&#xff0c;cp&#xff0c;mv命令&#xff0c;more&#xff0c;less&#xff0c;cat&#xff0c;tail&#xff0c;head&#xff0c;的使用[email protected] ~]# cp /usr/bin/ls /tmp/[[email protected] ~]# PATH$PATH:/tmp/ path的使用/usr/local/sbin…

进入Docker容器命令

进入Docker容器命令 docker执行命令: docker exec -it [容器ID或者容器名称] /bin/bash 如果出现下述问题&#xff1a; OCI runtime exec failed: exec failed: container_linux.go:344: starting container process caused "exec: \"/bin/bash\": stat /b…

dmalloc 原文 翻译整理

http://blog.csdn.net/cardinal_508/article/details/5553387 L13 从快速入门开始&#xff08;Quickstart&#xff09; 这个库是一个文件中所有简化用法中最常见的&#xff1a;FTP下载它&#xff0c;编译它&#xff08;-03&#xff09;&#xff0c;并连接到其他程序。 全部编译…

视频分辨率无损放大软件 Topaz Video Enhance AI 2.3.0

视频分辨率无损放大软件 Topaz Video Enhance AI 2.3.0 Topaz Video Enhance AI是一款非常好用的视频分辨率放大软件&#xff0c;用户可以通过这款软件将视频的分辨率进行自定义调节&#xff0c;最高能够将其放大至8K分辨率&#xff0c;并提供真实的细节和动作一致性&#xff…

linux 6.8 dns,CentOS6.8下安装DNS服务器

CentOS6.8下安装DNS服务器1、安装DNS服务器组件安装bind# yum install bind bind-libs bind-utils bind-chroot2、修改主配置文件/etc/named.conf需要修改的如下(带红色标注)&#xff1a;# vi /etc/named.confoptions {listen-on port 53{ any; };//listen-on-v6 port 53 { ::1…

delphi 10 seattle 中 解决IOS 9 限制使用HTTP 服务问题

IOS 9 于17号早上正式开始推送&#xff0c;早上起来立马安装&#xff0c;这次升级包只有1G&#xff0c; 安装空间也大大降低&#xff08;想起IOS 8 升级时&#xff0c;几乎把手机里面的东西删光了&#xff0c;满眼都是泪&#xff09;。 虽然安装后&#xff0c;网上几乎是铺天盖…

2022-2028年中国装备制造产业深度分析及发展规划咨询建议报告(全卷)

【报告类型】产业研究 【报告价格】4500起 【出版时间】即时更新&#xff08;交付时间约3个工作日&#xff09; 【发布机构】智研瞻产业研究院 【报告格式】PDF版 本报告介绍了中国装备制造行业市场行业相关概述、中国装备制造行业市场行业运行环境、分析了中国装备制造行…

安装flex4 plug-in插件的时候遇到老是在起始处安装不起

2019独角兽企业重金招聘Python工程师标准>>> 安装flex4 plug-in插件的时候遇到老是在起始处安装不起 解决方案&#xff1a;1、有可能你安装的目录有中文字符 2、你放安装文件的目录有中文字符 3、关闭360安全卫士和防火墙 转载于:https://my.oschina.net/u/1159401/…

Python教学课程分享10-异常处理结构

10.1 异常概念与常见表现形式 异常是一个事件&#xff0c;这个事件会在程序执行过程中发生&#xff0c;影响程序的正常进行。一般情况下&#xff0c;在Python无法正常进行程序时就会发生异常。异常是Python的对象&#xff0c;它表示一个错误&#xff0c;在Python脚本在发生异常…

24组8K真实路面材质贴图素材 VizPeople – Pavement Textures V1

24组8K真实路面材质贴图素材 VizPeople – Pavement Textures V1 24组8K真实路面材质贴图素材 VizPeople – Pavement Textures V1 大小解压后&#xff1a;5.98G 我们的第一个纹理收藏&#xff01;24个漂亮的无缝着色器&#xff0c;专为图形设计师和建筑可视化设计。现代和经…

linux查找项目中的问题,教你如何快速定位项目中慢查询[项目管理]

1. 使用对象&#xff1a; 项目经理或者项目管理者2. 数据库&#xff1a; mysql3. 快速定位慢查询&#xff1a;启动mysql时&#xff0c;启动慢查询日志&#xff1a;3.1 Window系统&#xff1a;第一种&#xff1a;bin\mysqlId.exe --safe-mode --slow-query-log (可在my.ini中配…

TCP的三次握手和四次分手

参考链接&#xff1a; http://blog.csdn.net/whuslei/article/details/6667471转载于:https://www.cnblogs.com/HuoAA/p/4826380.html

IDEA的Docker插件实战(Dockerfile篇)

IDEA的Docker插件实战(Dockerfile篇) IntelliJ IDEA的Docker插件能帮助我们将当前工程制作成Docker镜像、运行在指定的远程机器上&#xff0c;是学习和开发阶段的好帮手&#xff0c;本文一起来实战此插件的基本用法&#xff1b; 关于系列文章 本文是《IDEA的Docker插件实战》系…

技术变成客户才值钱

什么事与钱关联都显得有些俗&#xff0c;但没有钱又觉得这个世界这样的苦逼。作为一个技术人员&#xff0c;绝大多数人都在“苦逼”的生活中仰望“土豪”的生活&#xff0c;而唯一能够让我们达到这一目标的唯一途径就是将技术变成客户。技术不值钱似乎成了一个不争的实事&#…

浏览器会缓存js文件

项目中修改了一个js文件&#xff0c;然后重新发布到测试环境服务器&#xff0c;发现没有生效&#xff0c;页面依然报参数校验失败&#xff0c;经排查&#xff0c;发现浏览器中使用的还是旧的js文件&#xff0c;Chrome浏览器对js文件有缓存&#xff0c;只需要Ctrl shift del清…

视频色彩校正简介 Introduction to Video Color Correction

视频色彩校正简介 Introduction to Video Color Correction 视频色彩校正简介 Introduction to Video Color Correction MP4 |视频:h264&#xff0c;1280x720 |音频:AAC&#xff0c;44.1 KHz&#xff0c;2 Ch 云桥网络 平台获取教程&#xff01; 技能水平:初级中级|语言&…

linux下移动c盘文件位置,问个问题我在unbuntu下为何找不到windows c盘文件

问个问题我在unbuntu下为何找不到windows c盘文件发布时间:2008-08-08 08:07:13来源:红联作者:fzmhlxk这是不是和重ghost安装过xp有关啊是不是引导文件的问题我查看了 应到文件title Ubuntu 7.10, kernel 2.6.22-15-genericroot (hd0,6)kernel /boot/vmlinuz-2.6.22-15-generic…

一个妹子图应用客户端源码

源码GankMeizhi&#xff0c;也是一个干妹纸应用的客户端&#xff0c;目前该应用还没有上传到应用商店中&#xff0c;大家可以自行修改一下吧&#xff0c;没错。又是一个妹子图app&#xff0c;依然采集自干货集中营。 源码下载&#xff1a; http://code.662p.com/view/11060.ht…

2022-2028年中国专用化学品行业投资分析及前景预测报告

【报告类型】产业研究 【报告价格】4500起 【出版时间】即时更新&#xff08;交付时间约3个工作日&#xff09; 【发布机构】智研瞻产业研究院 【报告格式】PDF版 本报告介绍了中国专用化学品行业市场行业相关概述、中国专用化学品行业市场行业运行环境、分析了中国专用化…

【设计模式】从设计到模式

http://www.cnblogs.com/wangfupeng1988/p/3920332.html http://www.cnblogs.com/wangfupeng1988/p/3687346.html http://www.cnblogs.com/wangfupeng1988/p/3768304.html

SVN可以拉项目但是提交时提示没有权限

我SVN是有权限的&#xff0c;而且也能从服务器上拉下来项目&#xff0c;但就是提交的时候提示403没有权限。 最后通过百度经验和翻找博客解决。 原因是路径问题&#xff1a; SVN在拉取项目的时候不区分大小写&#xff0c;但是在提交时是严格区分大小写的。检查路径可以在工作主…

Lumion模型库 Unique Pro Lumion Library 2021

Lumion模型库 Unique Pro Lumion Library 2021 独特的专业图书馆2021 大小&#xff1a;12G 云桥网络 平台获取素材 这些包包括: 01–集总效果–准备渲染的外部设置 用于Lumion 8及以上 189档集总外观效果 – 02–集总效果–准备渲染的内部设置 用于Lumion 8及以上 2…

linux rm 提示io异常,Hadoop异常 java.io.IOException: Job status not available

Hadoop集群上跑mapreduce&#xff0c;在job任务执行完成退出时报 java.io.IOException: Job status not available异常。Job client请求job状态时&#xff0c;Application已经完成转而去Job history server请求job状态&#xff0c;就在这里抛出异常。[linuxidcmaster conf]$ ha…

【Winform】锐浪报表使用

在发开报表时&#xff0c;使用了锐浪报表。 需要注意的一些细节&#xff1a; 1、给staticbox设置文本&#xff0c;通过GridppReport的变量&#xff0c;使用ControlByName获取到控件后进行设置文字 _report.ControlByName("OrganizationName").AsStaticBox.Text &quo…

Spring cloud 微服务docker容器化最佳实践

Spring cloud 是当下最炙手可热的微服务套件&#xff0c;我们将介绍如何整合Docker容器达到高效快捷的构建发布 采用了dockerfile-maven-plugin插件发布镜像到远程docker主机&#xff0c;该部分详细教程请看 使用Maven插件快捷打包发布远程Docker镜像 添加docker插件依赖 如何…

sqlserver用sql语句创建链接服务器

2019独角兽企业重金招聘Python工程师标准>>> --创建 exec sp_addlinkedserver SHUA_LINK, , SQLOLEDB, 数据库IP exec sp_addlinkedsrvlogin SHUA_LINK, false,null, sa, 密码--查询 select top 10 * from SHUA_LINK.shua.dbo.shua_member order by regtime des…

[POJ3261] Milk Patterns

LINK 此题的常规做法是 二分 后缀数组 &#xff0c;但本蒟蒻还是习惯写 并查集 的做法 算法流程 1.离散化是肯定要有的&#xff0c;给的数据太大了&#xff0c;不离散化会RE 2.先跑一遍SA&#xff0c;把最重要的h数组求出来 3.把h从大到小排序&#xff0c;从大到小枚举重复串的…

风格化手绘纹理包 CGTrader – Stylized Mix Vol. 41 – Hand Painted Texture Pack

风格化手绘纹理包 CGTrader – Stylized Mix Vol. 41 – Hand Painted Texture Pack CGTrader–风格化混合第41卷–手绘纹理包 大小解压后&#xff1a;343M 信息: 7种风格化材料的包装。格式&#xff1a;. png .uproject .unitypackage 特点: 7种独特的纹理 包括基础颜色/正…