电子邮件收发系统设计.docx

上传人:牧羊曲112 文档编号:2093197 上传时间:2023-01-09 格式:DOCX 页数:40 大小:458.37KB
返回 下载 相关 举报
电子邮件收发系统设计.docx_第1页
第1页 / 共40页
电子邮件收发系统设计.docx_第2页
第2页 / 共40页
电子邮件收发系统设计.docx_第3页
第3页 / 共40页
电子邮件收发系统设计.docx_第4页
第4页 / 共40页
电子邮件收发系统设计.docx_第5页
第5页 / 共40页
点击查看更多>>
资源描述

《电子邮件收发系统设计.docx》由会员分享,可在线阅读,更多相关《电子邮件收发系统设计.docx(40页珍藏版)》请在三一办公上搜索。

1、目 录第1章 引 言2第2章 需求分析32.1 产品可行性分析32.2 产品功能需求分析52.2电子邮件系统收发邮件的过程5第3章 总体设计73.1 本系统的总体架构模型:73.2 系统模块的划分8第4章 详细设计94.1 接收邮件模块94.2 发送和回复邮件模块94.3 邮件处理模块104.4 界面实现的流程图104.5 邮件发送过程的流程图114.6 邮件接收流程134.7 用户鉴权和客户端配置信息流程154.8 阅读邮件流程16第5章 系统功能测试185.1 登陆界面及邮箱账户设置界面测试185.2 主界面测试185.3 发送界面与收件箱界面测试185.4 阅读邮件界面测试20第6章 结

2、论与展望216.1 结论216.2 展望21致 谢22参考文献23附录24第1章 引 言电子邮件(简称 E-mai1)又称电子信箱、电子邮政,表示通过电子通讯系统进行信件的书写、发送和接收,它是继电话、电报和传真之后最快捷、最方便的通讯工具,是 20 世纪人类最伟大的发明。早在互联网流行很久以前,电子邮件就已经存在。它是在主机-多终端的主从式体系中通过一台计算机终端向另一台计算机终端传送文本信息的相对简单方法发展起来的,也就是人们常说的 C/S 架构。如今,电子邮件已经将人与人越来越紧密地联系在一起,成为人们生活的一部分。通过电子邮件系统,人们可以用非常低廉的价格,以非常快速的方式,与世界上任

3、何一个网络用户联系。而电子邮件的形式也从原来的纯文本方式变成现在的 HTML 页面并加载附件的多彩形式,同时,人们还可以得到大量免费的新闻、专题邮件,并实现轻松的信息搜索,这是任何传统的方式也无法相比的。电子邮件的使用简易、投递迅速、收费低廉、易于保存、全球畅通无阻,使得它被广泛地应用。电子邮件收发系统基于Client/Server模式,主要功能通过收发电子邮件客户端程序实现。收发电子邮件需要标准的会话协议支持,SMTP(SimpleMailTransferProtocol)用于发送电子邮件,POP3协议(PostOfficeProtocol)用于接收电子邮件。电子邮件使人们的交流方式得到了极

4、大的改变.人们平时所发送或接收的电子邮件,并不是由本机来实现 SMTP 协议与 POP3 协议,电子邮件内容全是存储在相应服务商的 POP3 服务器上,用户必须要登录到相应的服务器上才能进行浏览、查询或者删除操作,但是,在网络繁忙或大家集中传输数据的时候,人们可能收不到消息或者打开很慢.为了解决这一难题,我们开发了电子邮件收发系统,将邮件服务器上的内容保存到本地机器上,这样即使在网络断开的情况下,也能查询已存在本地机器上的邮件。第2章 需求分析2.1 产品可行性分析整个电子邮件系统由电子邮件服务器端和电子邮件客户端组成,其工作过程及一些涉及到的协议如图2.1所示:图2.1 电子邮件系统工作过程

5、图其中SMTP是因特网电子邮件系统重要的应用层协议。它使用由TCP提供的可靠的数据传输服务把邮件消息从发信人邮箱所在邮件服务器传送到收信人邮箱所在邮件服务器。SMTP是客户-服务器应用模式,由发信人的邮件服务器执行的客户端和收信人的邮件服务器执行的服务器端组成。SMTP的客户端和服务器端同时运行在每个邮件服务器上。当一个邮件服务器向其它邮件服务器发送邮件消息时,它是作为SMTP客户端。当一个邮件服务器从其它邮件服务器接收邮件消息时,它是作为SMTP服务器端。SMTP规范定义在RFC 821中,它的作用是把邮件消息从发信人的邮件服务器传送到收信人的邮件服务器。SMTP限制所有邮件消息的信体必须是

6、简单的7位ASCII字符格式。这个限制使得二进制多媒体数据在由SMTP传送之前必须编码成7位ASCII文本;SMTP传送完毕之后,再把相应的7位ASCII文本邮件消息解码成二进制数据。POP3是RFC 1939中定义的一个简单的邮件访问协议,其功能有限。POP3开始于用户代理打开一个到POP3服务器端口号110的TCP连接。POP3服务器与邮件服务器运行在相同的服务器主机上,前者从用户的邮箱中读取并可能删除邮件消息,后者往用户的邮箱中写入邮件消息。TCP连接建立好之后,POP3依次经历授权认证、处理和更新3个阶段。在授权阶段,用户代理分别发出一个用户名和一个口令以认证下载邮件消息的用户。在处理

7、阶段,用户代理获取邮件消息,并可以标记待删除的邮件消息或去掉这些标记,获取邮件统计信息。更新阶段发生在用户代理发出quit命令以结束当前POP3会话之后,期间POP3服务器删除己加过删除标记的邮件消息。在POP3会话期间,用户代理发出命令,POP3服务器则对每个命令响应以一个应答。可能的应答有两个:指出刚才的命令执行成功的+OK(有时后跟一个解释性消息)和指出刚才的命令执行有误的-ERR。一个邮件的收发就是通过SMTP传递消息到对端邮件服务器,对端客户使用POP3协议从服务器上获得邮件的过程。在本设计中,采用自己编写基于socket的方法,来解析协议,进行邮件收发。同时,在进行邮件收发,需要提

8、供基于BASE64加密解密的鉴权信息,其中Base64是一种很简单的编码转换:对于待编码数据,以3个字节为单位,依次取6位数据并在前面补上两个0形成新的8位编码,由于38=46,这样3个字节的输入会变成4个字节的输出,长度上增加了1/3。上面的处理还不能保证得到的字符都是可见字符,为了达到此目的,Base64制定了一个编码表,进行统一的转换,见表2.1。码表的大小为26=64,这也是Base64名称的由来。由于编码是以3个字节为单位,当剩下的字符数量不足3个字节时,则应使用0进行填充,相应地,输出字符则使用=占位,因此编码后输出的文本末尾可能会出现1至2个=。表2.1 Base64编码表值编码

9、值编码值编码值编码值编码值编码值编码值编码0A8I16Q24Y32g40o48w5641B9J17R25Z33h41p49x5752C10K18S26a34i42q50y5863D11L19T27b35j43r51z5974E12M20U28c36k44s5206085F13N21V29d37l45t5316196G14O22W30e38m46u54262+7H15P23X31f39n47v55363/BASE64的加密解析,SUN公司有自己内部专用的API,该API位于JRE/LIB下,但是该API并没有javadoc,属于不推荐使用的方法,将在后续JDK版本中被剔除,因为本设计根据Base

10、64编码表,自行编写Base64加密解密方法。分析电子邮件传输过程中的协议和加密算法后,本设计进行自主开发是可行的。2.2 产品功能需求分析图2.2 系统总体功能图其中本设计实现的是一个电子邮件客户端,类似于Outlook,有用户邮箱账户设置,登陆验证,接收邮件,阅读邮件,保存邮件,发送邮件等功能。发送邮件:根据用户设置的公网邮箱账户或者一个公网不存在的自己私人域内的符合邮箱命名规范的邮箱账户,可实现对公网邮箱和本客户端(比如新浪,QQ,163)的邮件收发;若邮箱账户是自己随机设置的账户,则不可以向除本客户端以外的邮件服务器发送邮件;接收邮件:接收来自本客户端私人邮箱发来的邮件,在接收邮件的同

11、时,将对邮件进行默认保存,接收完成后,点击即可实现对邮件的阅读;登陆验证:客户端在启动的时候,会对用户的账户信息与客户端内部保存的信息,进行鉴权,防止旁人使用客户端乱发垃圾邮件;账号设置:这个功能主要是实现对邮件发送代理的选择,决定发送邮件功能的能力。2.2电子邮件系统收发邮件的过程图2.3 收发邮件过程图(1) 发信人调用用户代理来编辑要发送的邮件。用户代理用 SMTP 把邮件传送给发送端邮件服务器。(2) 发送端邮件服务器将邮件放入邮件缓存队列中,等待发送。(3) 运行在发送端邮件服务器的 SMTP 客户进程,发现在邮件缓存中有待发送的邮件,就向运行在接收端邮件服务器的 SMTP 服务器进

12、程发起 TCP 连接的建立。(4) TCP 连接建立后,SMTP 客户进程开始向远程的 SMTP 服务器进程发送邮件。当所有的待发送邮件发完了,SMTP 就关闭所建立的 TCP 连接。(5) 运行在接收端邮件服务器中的 SMTP 服务器进程收到邮件后,将邮件放入收信人的用户邮箱中,等待收信人在方便时进行读取。收信人在打算收信时,调用用户代理,使用 POP3(或 IMAP)协议将自己的邮件从接收端邮件服务器的用户邮箱中的取回(如果邮箱中有来信的)。第3章 总体设计3.1 本系统的总体架构模型:图3.1 系统的总体模型图图3.1是该客户端的系统架构图,图中包含了六个图形用户界面,两个邮件接收和发送

13、线程,以及一些相关的辅助方法和数据模型。其中,各个图形用户界面是为了方便用户使用该客户端而设计;用户鉴权和客户端配置信息,是主界面在加载时,针对每个特定的用户,加载其个人设置;用户信息模型和账户信息模型用来对用户进行登录验证,设置邮箱账户时的信息进行封装。发送邮件线程等待来自客户的发送请求,收到请求后,首先根据SMTP模型和用户输入信息,封装一个SMTP消息对象;接着对用户账户和密码进行BASE64加密;最后将封装好的信息对象,交由发送邮件方法进行发送;邮件接收线程是客户端加载成功后,就开始监听25端口,当有邮件信息发送到来时,将接收到的信息封装到一个未读邮件模型中去,然后将该模型传递给邮件接

14、收和保存方法,该方法将会对邮件在硬盘中进行保存,并更新客户端配置信息中得未读邮件信息。3.2 系统模块的划分按照本系统的总体功能划分,可以将这个电子邮件客户端分成5大模块,首先是登录模块,作为验证需要;其次是接收邮件模块,该模块负责邮件的接收,再次是发送模块,该模块负责该对方发送邮件;接着是邮件处理模块,该模块负责邮件的阅读、保存等操作;然后是邮件账户的管理,该操作负责设置客户端对公网的身份标识。图3.2给出了本系统的模块体系:图3.2 系统模块体系图第4章 详细设计4.1 接收邮件模块接收邮件模块主要由接收邮件线程监听端口完成对邮件的接收并对其进行保存和刷新主界面,包括下图中的几个部分。(1

15、) 接收邮件线程。一个邮件系统最基本的功能是能够接受发送的邮件。为了可以同时接收多个邮件,保持并发性,本设计使用java多线程的功能,设计一个可以多线程的接收邮件线程;(2) 保存邮件。接收到对方的邮件以后,必须先对邮件进行保存备份,然后将邮件信息封装到未读邮件模型后,再显示出来,可以隐去一些不必要的内容,只显示邮件关键信息给用户;(3) 刷新界面。当客户端收到一个邮件后,必须能够实时刷新主界面以提醒用户。接收邮件和附件模块的图示:图4.1 接收邮件和附件模块图4.2 发送和回复邮件模块发送邮件模块主要由发送邮件线程文件完成,包括图中的几个部分。(1) 编写新邮件。该部分也是电子邮件系统中最基

16、本的功能。(2) 发送新邮件。在编写完成新邮件后,电机该功能将邮件内容发送给对方。 发送邮件模块的图示:图4.2 发送邮件模块图4.3 邮件处理模块邮件处理模块主要对邮件进行阅读和保存功能,包括图中的几个部分。(1) 显示邮件内容,新建一个界面显示用户选择的邮件内容。(2) 保存邮件。在接收到邮件的同时,默认自动保存邮件。(3) 显示错误信息。在出现一些登录错误,删除错误,发送错误时,将显示不同的错误信息提示用户。邮件处理模块的图示:图4.3 邮件处理模块图4.4 界面实现的流程图如上所述,本设计的邮件客户端需要六个不同的界面,都采用java swing技术实现,java swing提供丰富的

17、图形组件和多样的布局方式,以及事件注册处理机制,在本设计中使用java swing技术实现这些界面,其流程如图4.4所示: 图4.4 界面实现流程图其中的部分代码如下:buttonPanel.add(newButton);buttonPanel.add(recButton);buttonPanel.add(recboxButton);buttonPanel.add(draftButton);buttonPanel.add(setButton);jFrame.setBounds(0, 0, SCREEN_WIDTH*3/4,SCREEN_HEIGHT*3/5);jFrame.setBackgro

18、und(Color.WHITE);jFrame.add(buttonPanel,new BorderLayout().WEST);jFrame.add(tab,new BorderLayout().CENTER);jFrame.setVisible(true);4.5 邮件发送过程的流程图邮件发送过程需要使用SMTP协议,因此在本设计中,将SMTP协议的各个字段封装到了一个对象中去,便于维护和管理,邮件发送的实现过程如图4.5所示,其部分实现代码如下String destip = getEmailNameInfo.getusername(username).replace(_, .);sock

19、et = new Socket(destip,PORT);BufferedReader br = getReader(socket);PrintWriter pw = getWriter(socket);sendAndReceive(null,br,pw);if(sendResult.equals(FAILED)JOptionPane.showMessageDialog(MainUI.jFrame, 连接邮件服务器失败!,null, 0);return;sendAndReceive(smtp.getMail(), br, pw);if(sendResult.equals(FAILED)retu

20、rn;sendAndReceive(smtp.getRept(), br, pw);if(sendResult.equals(FAILED)return;sendAndReceive(smtp.getData(), br, pw);if(sendResult.equals(FAILED)return;sendAndReceive(message.getFrom()+rn+message.getTo()+rn+message.getData(), br, pw);if(sendResult.equals(FAILED)JOptionPane.showMessageDialog(MainUI.jF

21、rame, 邮件发送失败!,null, 0);return;sendAndReceive(smtp.getQuit(), br, pw);if(sendResult.equals(FAILED)JOptionPane.showMessageDialog(MainUI.jFrame, 邮件发送成功!,null, 0);return; 图4.5 邮件发送过程其中邮件发送过程分为如下几步:1、 发送HELO命令,并等到回复,若回复争取,则发送下一个命令,若失败停止发送,下面步骤皆是如此处理;2、 发送EHLO命令;3、 发送 auth login命令,进行用户名和密码的鉴权请求;4、 发送BASE6

22、4加密后的用户名;5、 发送BASE6加密后的密码;6、 若鉴权成功发送mail from命令;7、 发送rcpt to命令,告知服务器邮件的接收方;8、 发送data命令,告知服务器接下来要发送邮件内容;9、 在本设计中邮件内容被封装到一个Message模型中,在本步中,发送的是该模型的一个对象;10、 在收到成功响应后,发送“.”结束发送过程。4.6 邮件接收流程邮件接收流程是该设计的基本功能之一,其使用的仍是SMTP协议流程,在本设计中,针对收到的邮件会将其封装到一个未读邮件的对象中去,具体流程如图4.6所示,其部分代码如下所示:图4.6 邮件接收流程while(request = br

23、.readLine()!=null)if(request.contains(mail from:) & request.contains() & request.contains(.com)| request.contains(.cn)isMAILFROM = true;pw.println(250 sender ok);continue;else if(!isMAILFROM)pw.println(500 command not recognized);continue;if(request.contains(rcpt to:) & request.contains() & request.

24、contains(.com)| request.contains(.cn)isRCPTTO = true;pw.println(250 recipient ok);continue;else if(!isRCPTTO)pw.println(500 command not recognized);continue;if(request.contains(data)isDATA = true;pw.println(354 enter content);continue;else if(!isDATA)pw.println(500 command not recognized);continue;i

25、f(isDATA)stringBuffer.append(request);stringBuffer.append(.);if(stringBuffer.toString().endsWith(.)isMessage = true;content = stringBuffer.toString().substring(0, stringBuffer.toString().length()-1);System.out.println(content is +content);pw.println(250 ok);if(request.contains(quit)pw.println(221 +g

26、etEmailNameInfo.getHostname(e_mailConfig.getEmailCFG().getEmailname();return;private PrintWriter getWriter(Socket socket) throws IOException / TODO Auto-generated method stubOutputStream out = socket.getOutputStream();return new PrintWriter(out, true); private BufferedReader getReader(Socket socket)

27、 InputStream is = null; try is = socket.getInputStream(); catch (IOException e) e.printStackTrace(); BufferedReader br = new BufferedReader(new InputStreamReader(is); return br; 4.7 用户鉴权和客户端配置信息流程该模块是在主界面加载前,针对不同的用户,加载相应的设置,其包含保存用户信息流程,更改用户信息流程,保存邮箱账户信息流程,更改邮箱账户信息流程,获取收到的邮件信息流程,设置邮件是否已读流程。其中这三组流程处理方

28、式一致,获取和更改用户信息流程如图4.7,4.8所示,部分处理代码如下。 4.7获取用户信息流程 4.8 更改用户信息流程图 protected User getUserProfile()User user = new User();SAXBuilder builder = new SAXBuilder();tryDocument doc = builder.build(USERFILE);Element rootElement = doc.getRootElement();String username = rootElement.getChild(USERNAME).getText();u

29、ser.setUsername(username);String password = rootElement.getChild(PWD).getText();user.setPassword(password);boolean login = new Boolean(rootElement.getChild(LOGIN).getText();user.setLogin(login);catch(Exception e)e.printStackTrace(); return user;protected void setUserProfile(User user)SAXBuilder buil

30、der = new SAXBuilder();try Document doc = builder.build(USERFILE);Element rootElement = doc.getRootElement();rootElement.getChild(USERNAME).setText(user.getUsername();rootElement.getChild(PWD).setText(user.getPassword();rootElement.getChild(LOGIN).setText(String.valueOf(user.isLogin();XMLOutputter f

31、mt=new XMLOutputter(); FileWriter writer=new FileWriter(USERFILE); org.jdom.output.Format f = org.jdom.output.Format.getPrettyFormat(); fmt.setFormat(f); fmt.output(doc, writer); writer.close();catch(Exception e)e.printStackTrace();4.8 阅读邮件流程邮件阅读是邮件系统的最基本功能之一,在本设计中,邮件阅读流程如图4.9所示,其代码如下String isread =

32、 String.valueOf(array.get(index-1).isRead();String name = array.get(index-1).getName();int length = name.length();int sindex = name.indexOf(_);user = name.substring(0, sindex);String rest = name.substring(sindex+1, length);int index2 = rest.indexOf(_);topic = rest.substring(0,index2);File file = new

33、 File(name+.txt);in = new DataInputStream(new BufferedInputStream(new FileInputStream(file);StringBuffer sb = new StringBuffer();String string = null;while(string=in.readLine()!=null)sb.append(string);string = sb.toString();BaseMain.setUnReadMail(user);showcontent(string);图 4.9 邮件阅读流程第5章 系统功能测试5.1 登

34、陆界面及邮箱账户设置界面测试界面模块主要使用java swing技术完成,其中包括主界面,登陆界面,设置账户界面,阅读邮件界面,发送邮件界面等几部分。登陆选择指定邮件用户和密码。在本系统中提供了一个用户名和密码均为admin的默认用户进行登录。使用默认用户登录后,用户可以更改登录账户。必须使用正确的用户名和密码才可以登录,不然无法进入客户端。登录界面的效果图: 图5.1 登录界面设置账户界面用来标识对公网的客户端身份,只有设置正确存在的公网账户才可以使用本客户端对外发送邮件。设置账户界面效果图:图5.2 邮箱账户设置界面5.2 主界面测试主界面是客户端与用户交互的直接体现,它调用相应的界面和方

35、法响应用户的操作,主界面见图5.3;图5.3 主界面5.3 发送界面与收件箱界面测试发送界面是发送邮件时的操作控制界面,主要有设置接收人,抄送,密送,邮件主题,邮件内容等5部分组成,发送界面见图5.4图5.4 发送邮件界面收件箱界面是登陆客户端时由邮箱配置方法将收到邮件信息设置在它下面,在主界面选择它后,即可查看客户端收到的邮件信息情况,收件箱界面见图5.5; 图5.5 收件箱界面5.4 阅读邮件界面测试阅读邮件界面是根据在收件箱界面的列表,选择一条未读邮件后,进行未读邮件内容的显示,阅读邮件界面见图5.6;图5.6 阅读邮件界面第6章 结论与展望6.1 结论系统主要实施对于邮件系统中邮件及邮

36、件夹的管理。系统主要实现了对于邮件的发送、接收、删除、邮件夹的管理等功能。6.2 展望系统开发是需要一个不断完善的过程,通过不断测试,检测出更多问题,并不断完善。然而由于时间的缘故,并不能进行逐步测试,因此仍然有很多地方需要改进。现在归纳如下:有时候邮件太长,或者是表格、Word文档,一正文方式发送不太方便,这样可以引用一个附件功能。及那个这些表格或Word文档以附件的形式上传,然后发送。在扩充一下,提供可以发送多个邮件的功能。但本系统未实现此功能。致 谢感谢我的指导老师彭晓天老师,本次论文的每个细节和每个数据,都离不开他的细心指导。无论在理论上还是在实践中,彭老师都给了我很大的帮助,使我得到

37、不少的提高这对于我以后的工作和学习都有一种巨大的帮助。另外,在系统开发过程中同学也给予我很大的帮助,帮助解决了不少的难点,使得系统能及时开发完成,这里一并表示感谢。 在论文即将完成之际,我的心情无法平静,从开始进入课题到论文的顺利完成,有许多可敬的师长、同学、朋友给了我无私的帮助,在这里请接受我诚挚的谢意!参考文献1张尧学等编著,计算机网络与Internet教程(第三版).北京:清华大学出版社,20012Computer Networks,Version Prentice Hall International,Inc.1998(计算机网络第四版,清华大学出版社影印版,2001)。3Intern

38、etworking with TCP/IP(Vol.1,Vol.2,Vol.3) Prentice Hall International,Inc.1995(TCP/IP网络互连技术卷1、卷2、卷3,清华大学出版社影印版,1998)。4谢希仁主编,计算机网络(第三版),北京:电子工业出版社,2000。附 录1、主界面主要代码public class MainUI extends BaseMainSuppressWarnings(unused)private static String title;private User user;private boolean isFirstLogin = f

39、alse;public static JFrame jFrame;public static final String WELCOME_WORD01 = 欢 迎 使 用 邮 件 客 户 端,WELCOME_WORD02 = 作 者 : 党 西 娇,WELCOME_WORD03 = 班 级 : 通 信 901;public static final String NEW = 写 信,RECEIVED = 收 信,RECBOX = 收件箱,DRAFT = 草 稿,SET = 设 置;public static final int BUTTON_NUMBER = 20,BUTTON_WIDTH =

40、30,BUTTON_HEIGHT = 20,BUTTON_START_POINT = 0;public static int DRAFT_EMAIL = 0;public static JButton newButton,recButton,recboxButton,contactButton,unreadButton,raftButton,sendButton,deleteButton,rabishboxButton,setButton;public static JTabbedPane tab;public static JPanel buttonPanel,sendPanel;publi

41、c Color colorStyle = new ColorColor.BLACK,Color.BLUE,Color.CYAN,Color.DARK_GRAY,Color.GRAY,Color.GREEN,Color.LIGHT_GRAY,Color.MAGENTA,Color.ORANGE,Color.PINK,Color.YELLOW,Color.RED;public JLabel start01,start02,start03;public JPanel labelPanel;public static final String DEFAULT_FONT = 宋体;public stat

42、ic int UNREADNUMBER = getUnreadCounter(BaseMain.getUnReadMailNumber();public static int DELETEDNUMBER = 1;private static boolean flag = false;private JPanel tempPanel;public MainUI(String title)this.title = title;public void start()initButton();initTable();user = getUserProfile();isFirstLogin = user

43、.isLogin();show(isFirstLogin);public void initButton() / TODO Auto-generated method stubnewButton = new JButton(NEW);newButton.setContentAreaFilled(false);newButton.setBackground(Color.WHITE);newButton.setForeground(Color.BLUE);newButton.addActionListener(listener);newButton.setBounds(BUTTON_START_POINT, BUTTON_START_POINT, BUTTON_W

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号