18.4 Network News

Network News, also known as Usenet News, is mostly transmitted with the Network News Transport Protocol (NNTP). The Python standard library supports this protocol in its module nntplib. The nntplib module supplies a class NNTP to connect to an NNTP server.

NNTP

class NNTP(
    host,port=119,user=None,passwd=None,readermode=False)

Returns an instance n of class NNTP connected to the given host and port, and optionally authenticated with the given user and passwd if user is not None. When readermode is True, also sends a 'mode reader' command; you may need this, depending on what NNTP server you connect to and on what NNTP commands you send to that server.

18.4.1 Response Strings

An instance n of NNTP supplies many methods. Each of n's methods returns a tuple whose first item is a string (referred to as response in the following section) that is the response from the NNTP server to the NNTP command corresponding to the method (method post just returns the response string, not a tuple). Each method returns the response string just as the NNTP server supplies it. The string starts with an integer in decimal form (the integer is known as the return code), followed by a space, followed by more text.

For some commands, the extra text after the return code is just a comment or explanation supplied by the NNTP server. For other commands, the NNTP standard specifies the format of the text that follows the return code on the response line. In those cases, the relevant method also parses the text in question, yielding other items in the method's resulting tuple, so your code need not perform such parsing itself; rather, you can just access further items in the method's result tuple, as specified in the following sections.

Return codes of the form 2xx, for any two digits xx, are success codes (i.e., they indicate that the corresponding NNTP command succeeded). Return codes of other forms, such as 4xx and 5xx, indicate failures in the corresponding NNTP command. In these cases, the method does not return a result. Rather, the method raises an instance of exception class nntplib.NNTPError or some appropriate subclass of it, such as NNTPTemporaryError for errors that may (or may not) be automatically resolved if you try the operation again, or NNTPPermanentError for errors that are sure to occur again if you retry. When a method of an NNTP instance raises an NNTPError instance e, the server's response string, starting with a return code such as 4xx, is accessible as str(e).

18.4.2 Methods

The most frequently used methods of an NNTP instance n are as follows.

article

n.article(id)

id is a string, either an article ID enclosed in angle brackets (<>) or an article number in the current group. Returns a tuple of three strings and a list (response,number,id,list), where number is the article number in the current group, id is the article ID enclosed in angle brackets, and list is a list of strings that are the lines in the entire article (headers then body, with an empty-line separator, and without end-of-line characters).

body

n.body(id,file)

id is a string, either an article ID enclosed in angle brackets (<>) or an article number in the current group. Returns a tuple of three strings and a list (response,number,id,list), where number is the article number in the current group, id is the article ID enclosed in angle brackets, and list is a list of strings that are the lines in the article's body, without end-of-line characters. When file is not None, it can be either a string naming a file that head then opens for writing, or a file object already open for writing. In either case, body writes the article's body to the file, and list in the tuple it returns is an empty list.

group

n.group(group_name)

Makes group_name the current group, and returns a tuple of five strings (response,count,first,last,group_name), where count is the total number of articles in the group, last is the number of the most recent article, first is the number of the oldest article, and group_name is the group's name. Normally, the group_name that is the last item in the returned tuple will be the same as the one you requested (i.e., the argument to n.group). However, an NNTP server could conceivably set up aliases, or synonyms; therefore, you should always check the last item of the returned tuple to ascertain what newsgroup has been in fact set as the current one.

head

n.head(id)

Returns an article's headers. id is a string, either an article ID enclosed in angle brackets (<>) or an article number in the current group. head returns a tuple of three strings and a list (response,number,id,list), where number is the article number in the current group, id is the article ID enclosed in angle brackets, and list is a list of strings that are the lines in the article's headers, without end-of-line characters.

last

n.last(  )

Returns a tuple of three strings (response,number,id), where number is the article number in the current group and id is the article ID, enclosed in angle brackets, for the last article in the current group.

list

n.list(  )

Returns a pair (response,group_stats), where group_stats is a list of tuples with information about each group on the server. Each item of group_stats is a tuple of four strings (group_name,last,first,group_flag), where group_name is the group's name, last is the number of the most recent article, first is the number of the oldest article, and group_flag is 'y' when you're allowed to post, 'n' when you're not allowed to post, and 'm' when the group is moderated.

newgroups

n.newgroups(date,time)

date is a string indicating a date, of the form 'yymmdd'. time is a string indicating a time, of the form 'hhmmss'. newgroups returns a pair (response,group_names), where group_names is the list of the names of groups created since the given date and time.

newnews

n.newnews(group,date,time)

group is a string that is either a group name, meaning you only want data about articles in that group, or '*', meaning you want data about articles in any newsgroup on the server. date is a string indicating a date, of the form 'yymmdd'. time is a string indicating a time, of the form 'hhmmss'. newnews returns a pair (response,article_ids), where article_ids is the list of the identifiers of articles received since the given date and time.

next

n.next(  )

Returns a tuple of three strings (response,number,id), where number is the article number in the current group and id is the article ID, enclosed in angle brackets, for the next article in the current group. The current group is set by calling n.group. Each time you call n.next, you receive information about another article (i.e., n implicitly maintains a pointer to a current article within the group and advances the pointer on each call to n.next). When there is no next article (i.e., the current article is the last one in the current group), n.next raises NNTPTemporaryError.

post

n.post(file)

Posts an article to the current group, reading it from file. file is a file-like object open for reading; post reads the article's headers and body from the file by repeatedly calling file.readline. Note that file must contain all needed headers, then an empty-line separator, then the body. post returns a string, the response from the server to the posting request.

quit

n.quit(  )

Closes the connection to the NNTP server. Call as the last method call on n.

stat

n.stat(id)

id is a string, either an article ID enclosed in angle brackets, or an article number in the current group. Returns a tuple of three strings (response,number,id), where number is the article number in the current group and id is the article ID enclosed in angle brackets.

18.4.3 Example

Here is a typical, simple example of nntplib use in an interactive interpreter session, using the free public NNTP server at sunsite.dk:

>>> import nntplib
>>> n = nntplib.NNTP('sunsite.dk')
>>> response, groups = n.list(  )
>>> print response
215 Newsgroups in form "group high low flags".
>>> print 'sunsite.dk carries', len(groups), 'newsgroups'
sunsite.dk carries 679 newsgroups
>>> linux_groups = [g for g in groups if g[0].startswith('linux')]
>>> print 'sunsite.dk carries', len(linux_groups), 'newsgroups about linux'
sunsite.dk carries 311 newsgroups about linux
>>> n.group('linux.postgres')
('211 13 974 986 linux.postgres', '13', '974', '986', 'linux.postgres')
>>> response, artnum, artid, headers = n.head('974')
>>> len(headers)
17
>>> [h for h in headers if h.startswith('Subject:')]
['Subject: newbie question on networking in postgresql']
>>> n.quit(  )
'205 .'


    Part III: Python Library and Extension Modules