MX record acquisition component writing

zhaozj2021-02-08  205

First, the application of MX record Email is the most successful application of the Internet so far. Improve the networker if there is no own Email mailbox, it will be difficult to call "netizen". The Internet is also increased with Email on the Internet. When we write network applications, we often need to involve embed Email applications into their own applications. This application is often used by using third-party Email related components, completes Email's writing, sending, charged, and decoding. During the transmission of email, the NT platform generally uses the CDO component comes with the NT system, and such components often rely on the service or a specific SMTP server in this unit, and cannot ensure that the letters arrive, and because There is a relay delay, and there is a possibility of lost letters. Therefore, many masters use direct Email to deliver Email sent directly to the destination mailbox, and implement this function key is three points: 1. MIME encoding 2, SMTP session control 3, MX record acquisition. Through my understanding, there are many articles about 1, 2 on the Internet. There are many corresponding referenced code, and for how to locate the target mailbox receiving server - get the MX record of the mailbox domain name, very few detailed discussion, search related components get one ASP environment server components (charges), there is no detailed source code. Based on this, I have written a similar component by learning Java language to help you understand the details of this. Second, DNS record classification and principles We know that the domain name system is the cornerstone of the Internet, we can access your interested websites through the names such as Yahoo.com is completely domain name system. When you tap www.yahoo.com, your browser doesn't know where the page pointing from this domain name, you will ask the set domain name resolution server (DNS), the domain name resolution server Looking for whether there is a request domain record, if there is a direct return, there is no need to resolve the server request (forward request) to the top level domain, until finally find the resolution record of this domain, tell you Which IP address is to get the relevant content. Such a process of converting the Internet domain name into a corresponding IP is called parsing. There are a variety of domain names, common with a (address) record, alias (CNAME) record, MX (mail exchange) record. A Record is a record of a domain name corresponding to an IP. The www.yahoo.com just mentioned corresponds to a query process of a record. Alias ​​records are mainly used to replace the domain name that already exist a record, such as www.yahoo.coms, www.yahoo.akadns.net, and further resolution www.yahoo.akadns.net Will get IP address 64.58.76.177. Mail exchange records are used for mail delivery. For example, you need to send an email to abc@yahoo.com, in general, your ISP's SMTP server (professional terminology is a mail agent, instead of user delivery) will accept letters you sent, then SMTP server Query Yahoo.com's MX records, see which server should be sent to which server, if you query Yahoo.com's MX record, then your ISP's SMTP server creates the TCP connection of the server specified by the MX record, and transmits Out your email to the destination server, complete the delivery process of Email.

If you get a domain name of the MX record, you get the way to direct delivery of the email, and you must get this MX record, you must be able to make your request to the domain name server DNS, but also understand DNS returned Information, read the content you need. The details of this are relatively complicated. I will briefly introduce it here: the client sends a UDP message to the 53-port of the DNS, then the server query (in the middle may be forwarded or referred to as recursive query), send back the client needs record, Also UDP packet. The general format of this type of message is: | 2 bytes Identifier | 2 bytes of logo | 2 bytes of problem number | 2 bytes of resource record number | 2 bytes authorized resource record number | 2 words Extra resource record number | Query domain (not fixed length) | Document (length is not fixed) | Authorized resource record (length not fixed) | Extra record information (length not fixed) identification field is used to point out The number of the message is generally specified by the customer. When the DNS server returns information, this identity is told to the client to answer which request. The 16-bit division of the flag field is 8 subfields, from left to right (high to low): QR 1 bit: 0 query packet 1 Response message OPCode 4 bit: usually 0, representation standard query, 1 reverse Query, 2 Server status query AA 1 bit: It is used to return packets, indicating whether it is an authorized answer TC 1 bit: Due to the length limit of UDP itself, it will tend to cut off the content of 512 bytes. This bit indicates whether the RD 1 can be truncated Bit: This is used to set it in the query message and returned by the server response packet. This bit tells the server to handle this query. If this bit is 0, and the authorized answer number is 0, then the server must return a list of other servers that can answer the query RA 1 bit: If the server supports recursive, then The server sets this bit in the response message. The subsequent 3bit must be 0 rcode 4 bit: Last to return code, 0 no error, 3 words error, that is, there is no record of the domain name to query on the server, generally used to return from the final authorization name server. The query problem is constructed by the query name query type query class. The query name consists of the sequence of multiple identifiers, each identifier, indicating the length of the identifier, and finally the name is ended by byte 0. For example, Cn..yahoo.com consists of 2 C N 5 Y A H O O 3 C O M 0. If this domain name is used, it is generally used in compression formats, then the first byte is not length, but a byte of the highest bit of 1, generally 0xc0, because there is no length of 64 identifier (due to Domain name specification). After the symbol byte of the compression format is the offset value of the original identity of the domain name. The query type is 2 bytes, and 1 means A record query 5 indicates that the CNAME record query 15 represents the MX record query. Class represents whether it is Internet data.

Recognize Record in the response message by the domain name (length not fixed) type (2 bytes) class (2 bytes) Survival time (4 bytes, second number) resource data length (2 bytes) resource data (not fixed) . The domain name format is the same as the query domain name format. Type, interpretation of the class with the query problem section. Resource data is different depending on the record type. If we follow the above format simultaneously combined with your needs, you can receive a UDP report to the server with a domain name resolution function, so that we can get the record. Therefore, mainly difficult to analyze the construction and response packets in the packet. Third, write the MX record component to start VJ. A DLL project is required, then modify the name of the main class name as the you want, the project is established. If everything is correct, you will get a DLL, with a domain name MX record query function. The specific code is seen from the source code analysis. The key is to construct query packets and interpretation of response messages in conjunction with your own query problem, and the server's network connection is UDP mode. For the sake of debugging, I added a main function entry, which can be used to call JVEW in the DOS window to see the result of the domain name MX record, and it is also convenient to debug. 4. Application examples and expansion There is such a query component, which can directly obtain the MX record of the domain name, which can help us get the delivery of Email. At the same time, we also know that the location of the domain name mail receives the server, and we can also get the mailbox user name by the post office of the domain name. You may be surprised by others, it is likely that some Email searches are queried by the MX record to get the address of the mail server, and then obtain different usernames by special username generation algorithms, one by one to get a mailbox. Add this feature in your application, you can pass your mail to the target, not dependent on the components on the server. Even you can write an email forwarding server, serving your user (the general sender is not open).

V. Source and analysis Import java.net. *; Import java.io. *; import java.util.StringTokenizer; // import java.util. *; / ** * this class is designed to be packaged with a com DLL output format. * The class has no standard entry points, other than the constructor. * Public methods will be exposed as methods on the default COM interface. * @ com.register (clsid = 20AE856F-E2F8-488E-B41E-753E6BEBD375, typelib = 36611559-AFAB-479E-8572-9A0B1F06CCDA) * / public class MXDNS {private String theDnsServer; // the address of the current DNS server private DatagramPacket outPk; // send packets private DatagramPacket inPk; // receive packet private DatagramSocket UDPSocket; // UDP Tao Putter PRIVATE INETDRESS DNSSERVERIP; // Domain Name Resolution Server IP Private INT POSITION, ID, LENGTH; // Analysis DNS DVATE STRING DMNAME; // Query Domain Name Private MXREC MXRECS; // DNS Answer Record Private Static Int DNS_Port = 53; // DNS Service Port Private Byte [] Pkdata = New Byte [512]; // Get 512 bytes of Packet PUBLIC MXDNS () // Constructor {ID = New java.util.date ()). getseconds () * 60 * (new java.util.random ()). Nextint (); // Get unique ID} // below is exposed attributes and methods Pub Lic void setDnsserver (String DNSSERVER) {these DNSERVER = DNSSERVER; / / Set the name of the current DNS server or IP} public string getMxRecords (String DM) // Get all DNSMX record arrays {Return (GetMxRecords (DM, THEDNSSERVER); } public String getMXRecords (String dm, String DNSServer) {try {DNSServerIP = InetAddress.getByName (DNSServer); // get the DNS server InetAddress outPk = new DatagramPacket (pkdata, pkdata.length, DNSServerIP, DNS_PORT); // outgoing Datasters udpsocket = new datagramsocket (DNS_PORT); // Packet port MakednsQuery (ID, DM); // Generate Query Packet UDPSocket.send (OUTPK); // Send Data Packet Inpk = New DataGrampacket (Pkdata, Pkdata .length; udpsocket.receive (inPK); // Receive returned answer packets pkdata = INPK.GETDATA (); // Get the word LENGTH = Pkdata.length;

} catch (unknownHOSTEXCEPTION UE) {} catch (socketexception se) {} catch (ioException ie) {} return ()); // Analysis returned data packets, get logged results} public void Makednsquery (int ID, STRING DM) {// Generate query data for in the PKDATE BYTE array (INT i = 0; i <512; i ) {pkdata [i] = 0;} PKDATA [0] = (Byte) (ID >> 8); PKDATA [1] = (Byte) (ID & 0xFF); // Query ID 2 byte pkdata [2] = (Byte) 1; // Qrbit bit is 1, indicating that the query packet pkdata [3] = BYTE) 0; pkdata [4] = (byte) 0; pkdata [5] = (byte) 1; // 1 problem pkdata [6] = (byte) 0; // Resource record number, authorized resource record, additional The resource record is 0, because it is query packet pkdata [7] = (byte) 0; pkdata [8] = (byte) 0; pkdata [9] = (byte) 0; pkdata [10] = (Byte) 0; PKDATA [11] = (byte) 0; StringTokenizer St = New StringTokenizer (DM, "."); //. Sategage domain name string label; position = 12; // From the 12th byte to generate a query problem while ( St.hasmoreToKens ()) {label = st.nextToken (); pkdata [position ] = (Byte) (Byte) (bTE) (= Label.getbytes () (); For (int J = 0; j {

PKDATA [POSITION ] = B [J];

}

}

Pkdata [Position ] = (Byte) 0; // End the domain name

Pkdata [Position ] = (Byte) 0;

Pkdata [Position ] = (Byte) 15; // Query Type 15 Represents MX Record Query

Pkdata [Position ] = (Byte) 0;

Pkdata [Position ] = (Byte) 1; // Internet Data Record Inquiry

} // Constructed query completion

Private string getResponse () // Get feedback

{

String temp = "";

INT Qcount = ((PKDATA [4] & 0xFF) << 8) | (PKDATA [5] & 0xFF); // Number of questions

IF (qcount <0)

{RETURN ("");} // problem number less than 0, return empty string

INT ACOUNT = ((PKDATA [6] & 0xFF) << 8) | (PKData [7] & 0xFF); // Get the number of answers

IF (ACOUNT <0)

{RETURN ("");} // problem number less than 0, return empty string

Position = 12; // Query the problem part start position

For (int i = 0; i

{

DMNAME = ""

Position = proc (position);

Position = 4; // Increase the length byte part of the query type, query class}

For (int i = 0; i

{

DMNAME = ""

Position = proc (position);

Position = 10; // Type 2 bytes, class 2 bytes, survival time 4 bytes, resource length 2 bytes Total 10 bytes

INT pref = (PKData [POSITION ] << 8) | (PKDATA [POSITION ] & 0xFF); // Get MX recorded exchanger base

DMNAME = ""

Position = proc (position); // Get the value of the exchanger, generally a standard domain name

IF (temp.equalsignorecase ("))

{TEMP = " pref " " DMNAME;} // Return data

Else

{TEMP = Temp "," Pref " DMName;}

}

Return (TEMP);

}

Private int proc (int position)

{// This process is looking for domain names from the PKData byte array

INT LEN = (PKDATA [POSITION ] & 0xFF); // Get the length of the identifier to process the identifier

IF (len == 0) // No other identifier, end return

{RETURN POSITION;

INT offset; // offset

Do {

IF ((len & 0xc0) == 0xc0) // Compressed format

{

If (position> = length) // exceeds the size of the package, then the offset is obviously wrong

{RETURN (-1);

OFFSET = ((Len & 0x3f) << 8) | (PKDATA [POSITION ] & 0xFF); // Get offset of the compression source identifier

Proc (Offset); // Recursive call to get the name before compression

Return (position);

}

ELSE // Non-compressed format

{

IF ((Position Len)> Length) // More than the length

{RETURN (-1);

DMNAME = New String (PKDATA, POSITION, LEN); // Get various parts of the domain name identifier

Position = LEN;

}

IF (Position> Length)

{RETURN (-1);

Len = pkdata [position ] & 0xff; // Last 0 ends?

IF (len! = 0)

{

DMNAME = "."; // plus. Compositions complete domain names

}

} while (len! = 0);

Return (position);

}

Public static void main (string args []) THROWS EXCEPTION

{

MXDNS MX = New MXDNS ();

String s = mx.getmxRecords ("sina.com", "202.96.128.68");

System.out.println (s);

INT k = system.in.read ();

}

}

转载请注明原文地址:https://www.9cbs.com/read-3063.html

New Post(0)