RFC 1081

Post Office Protocol: Version 3

๐Ÿ“… published November 1988, from ietf

Post Office Protocol - Version 3 ๐Ÿ“ฌ๐ŸŽ€

Okay bestie, this one is RFC 1081 and it's giving "send me my mail from my tiny computer" ๐Ÿ’… It was written by M. Rose from TWG and dated November 1988. The Status section calls it a proposed protocol for the Internet community, so that's its category โœจ Nothing in its title block says it obsoletes or updates another RFC. It does say it's based on RFC 918 (since revised as RFC 937) ๐Ÿฆ‹


Status of this Memo ๐ŸŒธ

Okay so this memo suggests a simple method for workstations to dynamically access mail from a mailbox server ๐Ÿ“ฌ It's a proposed protocol for the Internet community, and it's literally asking for discussion and suggestions for improvements ๐Ÿซถ Distribution of this memo is unlimited ๐ŸŒˆ

This memo is based on RFC 918 (since revised as RFC 937). Even though it's similar in form to the original Post Office Protocol (POP) proposed for the Internet community, it's similar in spirit to the ideas investigated by the MZnet project at the University of California, Irvine โœจ

Substantial work was also done on examining POP in a PC-based environment, and that work added extra functionality to this protocol ๐Ÿ’– It was done by the ACIS Networking Systems Group at Stanford University, and the author is super grateful for their interest ๐Ÿ™ˆ

Introduction ๐Ÿงš

So on certain smaller nodes in the Internet, it's often impractical to maintain a message transport system (MTS) ๐Ÿ˜ญ A workstation might not have enough resources (cycles, disk space) to keep an SMTP server and its local mail delivery system resident and running all the time ๐Ÿ’€ It can also be expensive (or impossible) to keep a personal computer connected to an IP-style network for long stretches, because that node is lacking the resource known as "connectivity" ๐Ÿ™ƒ

Even so, managing mail on these smaller nodes is still super useful, and they often support a user agent (UA) to help with mail handling ๐Ÿ’… So the fix is that a node which can support an MTS entity offers a maildrop service to these less endowed nodes ๐Ÿ‘‘ POP3 (Post Office Protocol - Version 3) is meant to let a workstation dynamically access a maildrop on a server host in a useful way ๐Ÿ“ Usually that means the workstation uses POP3 to retrieve mail the server is holding for it โœจ

For the rest of this memo, a "client host" is a host using the POP3 service, and a "server host" is a host offering the POP3 service ๐Ÿฆ‹

A Short Digression ๐ŸŽ€

This memo doesn't specify how a client host gets mail into the transport system ๐Ÿ™ˆ But it does present a method that fits the philosophy of this memo:

When the user agent on a client host wishes to enter a message
into the transport system, it establishes an SMTP connection to
its relay host (this relay host could be, but need not be, the
POP3 server host for the client host).

If you follow that method, the client host looks like a user agent to the MTS, and it should NOT be regarded as a "trusted" MTS entity in any sense whatsoever ๐Ÿšจ This idea, along with POP3's role as part of a split-UA model, gets talked about later in the memo ๐Ÿ”ฅ

Here's how the service starts up. The server host starts POP3 by listening on TCP port 110 ๐ŸŒˆ When a client host wants to use the service, it opens a TCP connection with the server host. Once that connection is up, the POP3 server sends a greeting ๐Ÿ‘‹ After that, the client and POP3 server take turns sending commands and responses until the connection is closed or aborted ๐Ÿ’œ

Commands in POP3 are a keyword, possibly followed by an argument. Every command ends with a CRLF pair โœจ

Responses in POP3 are a success indicator, then a keyword, possibly followed by more information. Every response ends with a CRLF pair too ๐Ÿ’– There are two success indicators right now: positive ("+OK") and negative ("-ERR") ๐Ÿ“

Some commands get multi-line responses, and the memo clearly marks those below ๐Ÿงš For these, you send the first line of the response plus a CRLF, then any extra lines, each ending with a CRLF pair. When every line has been sent, you send a final line that's just a termination octet (decimal code 046, ".") and a CRLF pair ๐Ÿซถ If any line in a multi-line response starts with the termination octet, that line gets "byte-stuffed", which means you prepend another termination octet to it ๐Ÿ™ˆ So a multi-line response ends with the five octets "CRLF.CRLF" ๐Ÿ˜ญ

When the client reads a multi-line response, it checks whether the line starts with the termination octet. If it does, and octets other than CRLF follow, the first octet of the line (the termination octet) gets stripped away ๐Ÿ’… If CRLF comes right after the termination character, the POP server's response is over, and that ".CRLF" line doesn't count as part of the multi-line response ๐Ÿ‘‘

A POP3 session moves through a few states over its lifetime ๐ŸŒธ Once the TCP connection is open and the POP3 server has sent the greeting, the session enters the AUTHORIZATION state. In this state, the client must identify itself to the POP3 server ๐Ÿ” After it does that successfully, the server acquires resources tied to the client's maildrop, and the session enters the TRANSACTION state ๐Ÿ’ซ Here the client asks the POP3 server to do things. When the client is done with its transactions, the session enters the UPDATE state ๐Ÿฆ‹ In this state, the POP3 server releases whatever resources it acquired during the TRANSACTION state and says goodbye ๐Ÿ‘‹ Then the TCP connection gets closed ๐ŸŒˆ

The AUTHORIZATION State ๐Ÿ”

Once a POP3 client opens the TCP connection, the POP3 server sends a one-line greeting ๐Ÿ’– It can be any string ending in CRLF. Here's an example:

S.  +OK dewey POP3 server ready (Comments to: PostMaster@UDEL.EDU)

Heads up, this greeting is a POP3 reply ๐Ÿšจ The POP3 server should always give a positive response as the greeting โœจ

Now the session is in the AUTHORIZATION state ๐ŸŽ€ The client must issue the USER command next. If the POP3 server answers the USER command with a positive success indicator ("+OK"), the client may issue either the PASS command to finish authorization, or the QUIT command to end the POP3 session ๐Ÿ’… If the server answers the USER command with a negative success indicator ("-ERR"), the client may issue a new USER command or the QUIT command ๐Ÿ™ƒ

When the client issues the PASS command, the POP3 server uses the argument pair from the USER and PASS commands to decide whether the client should get access to the right maildrop ๐Ÿ”‘ If so, the POP3 server acquires an exclusive-access lock on the maildrop. If it gets the lock, the server parses the maildrop into individual messages (see the note below), figures out the last message (if any) in the maildrop that was referenced by the RETR command, and replies with a positive success indicator ๐ŸŽ‰ The session then enters the TRANSACTION state ๐Ÿฆ‹

If the lock can't be acquired, or the client is denied access to that maildrop, or the maildrop can't be parsed for some reason, the POP3 server replies with a negative success indicator ๐Ÿ˜ญ (If the server acquired a lock but still plans to reply with a negative success indicator, it must release the lock before rejecting the command ๐Ÿ”ฅ) At that point, the client may issue a new USER command and start over, or it may issue the QUIT command ๐Ÿ’œ

NOTE: Minimal implementations of POP3 only need to be able to break a maildrop into its component messages. They need NOT be able to parse individual messages. More advanced implementations may wish to have this capability, for reasons discussed later. ๐Ÿงš

After the POP3 server parses the maildrop into individual messages, it gives each message a message-id and notes the size of the message in octets ๐Ÿ“ The first message in the maildrop gets a message-id of "1", the second gets "2", and so on, so the n'th message in a maildrop gets a message-id of "n" โœจ In POP3 commands and responses, all message-ids and message sizes are written in base-10 (decimal) ๐Ÿ”ข

The server also sets the "highest number accessed" to the message number of the last message referenced by the RETR command ๐Ÿ’–

Here are the summaries for the three POP3 commands we've covered so far ๐ŸŒˆ

USER name
    Arguments: a server specific user-id (required)
    Restrictions: may only be given in the AUTHORIZATION
        state after the POP3 greeting or after an
        unsuccessful USER or PASS command
    Possible Responses:
        +OK name is welcome here
        -ERR never heard of name
    Examples:
        C:    USER mrose
        S:    +OK mrose is a real hoopy frood
          ...
        C:    USER frated
        S:    -ERR sorry, frated doesn't get his mail here

PASS string
    Arguments: a server/user-id specific password (required)
    Restrictions: may only be given in the AUTHORIZATION
        state after a successful USER command
    Possible Responses:
        +OK maildrop locked and ready
        -ERR invalid password
        -ERR unable to lock maildrop
    Examples:
        C:    USER mrose
        S:    +OK mrose is a real hoopy frood
        C:    PASS secret
        S:    +OK mrose's maildrop has 2 messages
              (320 octets)
          ...
        C:    USER mrose
        S:    +OK mrose is a real hoopy frood
        C:    PASS secret
        S:    -ERR unable to lock mrose's maildrop, file
              already locked

QUIT
    Arguments: none
    Restrictions: none
    Possible Responses:
        +OK
    Examples:
        C:    QUIT
        S:    +OK dewey POP3 server signing off

The TRANSACTION State ๐ŸŽ€

okay bestie, once the client has successfully identified itself to the POP3 server and the POP3 server has locked and burst the right maildrop, the session is officially in the TRANSACTION state ๐Ÿ’…. The client can now issue any of the POP3 commands below, as many times as it wants. After every command, the server sends back a response. Eventually the client sends QUIT and the session enters the UPDATE state ๐Ÿฆ‹.

Here are the POP3 commands that are valid in the TRANSACTION state โœจ

STAT

Arguments: none

Restrictions: may only be given in the TRANSACTION state.

Discussion:

The server sends a positive response with a line of info about the maildrop. This line is called a "drop listing" for that maildrop ๐Ÿ“ฌ

To keep parsing simple, all POP3 servers are required to use a certain format for drop listings. The first octets present must show the number of messages in the maildrop. After that comes the size of the maildrop in octets. This memo doesn't put any requirement on what comes after the maildrop size ๐Ÿคทโ€โ™€๏ธ Minimal implementations should just end that line of the response with a CRLF pair. More advanced implementations may include other information.

NOTE: This memo STRONGLY discourages implementations from supplying additional information in the drop listing. Other, optional, facilities are discussed later on which permit the client to parse the messages in the maildrop. ๐Ÿ™ˆ

Messages marked as deleted are not counted in either total ๐Ÿ—‘๏ธ

Possible Responses: +OK nn mm

Examples:

C:    STAT
S:    +OK 2 320

LIST [msg]

Arguments: a message-id (optionally). If a message-id is given, it may NOT refer to a message marked as deleted.

Restrictions: may only be given in the TRANSACTION state.

Discussion:

If an argument was given and the server sends a positive response, the line it sends has info for that one message. This line is called a "scan listing" for that message ๐Ÿ”

If no argument was given and the server sends a positive response, the response is multi-line. After the initial +OK, the server sends one line for each message in the maildrop. Each line has info for that message, and each one is also called a "scan listing" ๐Ÿ“‹

Again, all POP3 servers are required to use a certain format for scan listings, so parsing stays easy ๐Ÿ’– The first octets present must be the message-id of the message. After the message-id comes the size of the message in octets. This memo doesn't put any requirement on what comes after the message size in the scan listing. Minimal implementations should just end that line of the response with a CRLF pair. More advanced implementations may include other information, as parsed from the message.

NOTE: This memo STRONGLY discourages implementations from supplying additional information in the scan listing. Other, optional, facilities are discussed later on which permit the client to parse the messages in the maildrop. ๐Ÿ™ƒ

Messages marked as deleted are not listed at all ๐Ÿ’€

Possible Responses:

+OK scan listing follows -ERR no such message

Examples:

C:    LIST
S:    +OK 2 messages (320 octets)
S:    1 120
S:    2 200
S:    .
  ...
C:    LIST 2
S:    +OK 2 200
  ...
C:    LIST 3
S:    -ERR no such message, only 2 messages in
      maildrop

RETR msg

Arguments: a message-id (required). This message-id may NOT refer to a message marked as deleted.

Restrictions: may only be given in the TRANSACTION state.

Discussion:

If the server sends a positive response, the response is multi-line. After the initial +OK, the server sends the message that matches the given message-id ๐Ÿ“จ The server has to be careful to byte-stuff the termination character, same as with all multi-line responses ๐Ÿงต

If the number for this message is higher than the "highest number accessed" in the maildrop, the server updates the "highest number accessed" to that number ๐Ÿ“ˆ

Possible Responses:

+OK message follows -ERR no such message

Examples:

C:    RETR 1
S:    +OK 120 octets
S:    <the POP3 server sends the entire message here>
S:    .

DELE msg

Arguments: a message-id (required). This message-id may NOT refer to a message marked as deleted.

Restrictions: may only be given in the TRANSACTION state.

Discussion:

The server marks the message as deleted ๐Ÿท๏ธ After that, any future reference to the message-id tied to that message in a POP3 command gives an error. The server does not actually delete the message until the session enters the UPDATE state, so it's not gone yet ๐Ÿ‘€

If the number for this message is higher than the "highest number accessed" in the maildrop, the server updates the "highest number accessed" to that number ๐Ÿ“ˆ

Possible Responses:

+OK message deleted -ERR no such message

Examples:

C:    DELE 1
S:    +OK message 1 deleted
  ...
C:    DELE 2
S:    -ERR message 2 already deleted

NOOP

Arguments: none

Restrictions: may only be given in the TRANSACTION state.

Discussion:

The server does nothing. It just replies with a positive response ๐Ÿ˜ด (iconic energy, honestly ๐Ÿซถ)

Possible Responses: +OK

Examples:

C:    NOOP
S:    +OK

LAST

Arguments: none

Restrictions: may only be issued in the TRANSACTION state.

Discussion:

The server sends a positive response with a line that has the highest message number that has been accessed ๐Ÿ•ต๏ธโ€โ™€๏ธ If no message in the maildrop has been accessed during previous transactions, the server returns zero. After that, a client can infer that any messages numbered higher than the LAST response are messages it hasn't accessed yet ๐Ÿ‘‘

Possible Response: +OK nn

Examples:

C:      STAT
S:      +OK 4 320
C:      LAST
S:      +OK 1
C:      RETR 3
S:      +OK 120 octets
S:      <the POP3 server sends the entire message
        here>
S:      .
C:      LAST
S:      +OK 3
C:      DELE 2
S:      +OK message 2 deleted
C:      LAST
S:      +OK 3
C:      RSET
S:      +OK
C:      LAST
S:      +OK 1

RSET

Arguments: none

Restrictions: may only be given in the TRANSACTION state.

Discussion:

If the server has marked any messages as deleted, it unmarks them ๐Ÿ”„ The server then sends a positive response. The "highest number accessed" also gets reset to the value that was determined at the beginning of the POP3 session ๐ŸŒธ

Possible Responses: +OK

Examples:

C:    RSET
S:    +OK maildrop has 2 messages (320 octets)

The UPDATE State ๐ŸŒˆ

When the client issues the QUIT command from the TRANSACTION state, the session enters the UPDATE state. (Heads up though: if the client issues QUIT from the AUTHORIZATION state, the session terminates but does NOT enter the UPDATE state ๐Ÿšซ)

QUIT

Arguments: none

Restrictions: none

Discussion:

The server removes all messages marked as deleted from the maildrop ๐Ÿงน It then releases the exclusive-access lock on the maildrop and replies about whether those operations worked. After that, the TCP connection gets closed ๐Ÿ‘‹

Possible Responses: +OK

Examples:

C:    QUIT
S:    +OK dewey POP3 server signing off (maildrop
      empty)
  ...
C:    QUIT
S:    +OK dewey POP3 server signing off (2 messages
      left)
  ...

Optional POP3 Commands โœจ

okay so the POP3 commands from before MUST be supported by every minimal POP3 server, no exceptions ๐Ÿซถ

these optional ones are where it gets fun. they give the POP3 client way more freedom in how it handles messages, and the server stays simple ๐Ÿ’…

NOTE: This memo STRONGLY encourages implementations to support these commands instead of building augmented drop and scan listings. The big idea here is to put the smarts in the POP3 client, NOT the POP3 server ๐Ÿง ๐ŸŽ€

TOP msg n

Arguments: a message-id (required) and a number. This message-id MAY NOT refer to a message marked as deleted.

Restrictions: MAY only be given in the TRANSACTION state.

Discussion:

If the POP3 server sends a positive response, the response is multi-line. After the initial +OK, the server sends the headers of the message, the blank line that separates the headers from the body, and then the number of lines asked for from the message body. It has to byte-stuff the termination character too, same as with every multi-line response ๐ŸŒธ

If the client asks for more lines than the body actually has, the server just sends the whole message. no drama ๐Ÿฆ‹

Possible Responses:

+OK top of message follows
-ERR no such message

Examples:

C:    TOP 10
S:    +OK
S:    <the POP3 server sends the headers of the
       message, a blank line, and the first 10 lines
       of the body of the message>
S:    .
  ...
C:    TOP 100
S:    -ERR no such message

RPOP user

Arguments: a client specific user-id (required)

Restrictions: MAY only be given in the AUTHORIZATION state after a successful USER command. On top of that, it MAY only be given if the client connected to the server from a reserved (privileged) TCP port ๐Ÿ”’

Discussion:

RPOP can be used INSTEAD of PASS to authenticate access to the maildrop. For it to work, the POP3 client MUST use a reserved TCP port (port < 1024) to connect to the server ๐Ÿงš

The server uses the USER and RPOP argument pair to decide whether the client gets access to the right maildrop. The difference from PASS is that the server checks whether the remote user named in the RPOP command, who lives on the POP3 client host, is allowed to access the maildrop of the user named in the USER command (on Berkeley UNIX, that's the .rhosts mechanism). Other than this authentication difference, RPOP works exactly like PASS ๐Ÿ’–

ngl this is the scary part. this memo says that using this feature has let way more hosts on local networks (and sometimes remote networks) get broken into by people guessing passwords or breaking in other ways. so be careful with it ๐Ÿ˜ญ๐Ÿšจ

Possible Responses:

+OK maildrop locked and ready
-ERR permission denied

Examples:

C:    USER mrose
S:    +OK mrose is a real hoopy frood
C:    RPOP mrose
S:    +OK mrose's maildrop has 2 messages (320
      octets)

Minimal POP3 Commands ๐ŸŽ€

Here's the full list of the minimal commands, grouped by state so you can see where each one is valid ๐Ÿ‘‘

Minimal POP3 Commands:
    USER name               valid in the AUTHORIZATION state
    PASS string
    QUIT

    STAT                    valid in the TRANSACTION state
    LIST [msg]
    RETR msg
    DELE msg
    NOOP
    LAST
    RSET
    QUIT                    valid in the UPDATE state

Optional POP3 Commands:
    RPOP user               valid in the AUTHORIZATION state

    TOP msg n               valid in the TRANSACTION state

POP3 Replies:
    +OK
    -ERR

Here's the tea โ˜•: other than STAT, the only thing the client really cares about in a server's reply is "+OK" or "-ERR". Anything that comes after that can be ignored by the client ๐Ÿ™ˆ

Example POP3 Session ๐Ÿ’Œ

Let's watch a whole session play out, from connection to sign-off ๐Ÿ“

S: <wait for connection on TCP port 110>
    ...
C: <open connection>
S:    +OK dewey POP3 server ready (Comments to: PostMaster@UDEL.EDU)
C:    USER mrose
S:    +OK mrose is a real hoopy frood
C:    PASS secret
S:    +OK mrose's maildrop has 2 messages (320 octets)
C:    STAT
S:    +OK 2 320
C:    LIST
S:    +OK 2 messages (320 octets)
S:    1 120
S:    2 200
S:    .
C:    RETR 1
S:    +OK 120 octets
S:    <the POP3 server sends message 1>
S:    .
C:    DELE 1
S:    +OK message 1 deleted
C:    RETR 2
S:    +OK 200 octets
S:    <the POP3 server sends message 2>
S:    .
C:    DELE 2
S:    +OK message 2 deleted
C:    QUIT
S:    +OK dewey POP3 server signing off (maildrop empty)
C:  <close connection>
S:  <wait for next connection>

Message Format ๐Ÿ“จ

Every message sent during a POP3 session is assumed to follow the standard for the format of Internet text messages [RFC822]. so the messages stay in proper shape ๐Ÿ’…

Heads up, though: the byte count a message has on the server host can be different from the octet count given to that message, because of local conventions for marking end-of-line. Usually, during the AUTHORIZATION state, the POP3 client can work out the size of each message in octets when it splits the maildrop into messages. For example, if the server host stores end-of-line as one character, the server just counts each occurrence of that character in a message as two octets ๐Ÿงฎ

Lines in the message that start with the termination octet don't need to be counted twice, because the POP3 client removes all the byte-stuffed termination characters when it gets a multi-line response โœจ

The POP and the Split-UA model ๐Ÿฆ‹

The core idea behind POP3 is a split-UA model. The POP3 client host is a remote PC-based workstation that acts ONLY as a client of the message transport system. It doesn't offer delivery or authentication services to anyone else. So it's acting as a UA on behalf of whoever is using the workstation ๐Ÿ–ฅ๏ธ

That gives us two UA functions that talk to the message transport system: Posting (SMTP) and Retrieval (POP3). The entity that supports this kind of setup is called a split-UA, because the user agent is split between two hosts that have to work together to provide these functions ๐Ÿซถ

ASIDE: Others might call this a remote-UA instead. There are good arguments for both terms.

This memo explicitly names TCP as the transport for POP3. That doesn't HAVE to be the case ๐ŸŒˆ In the MZnet split-UA, for example, the personal micro-computers don't have IP-style networking. A PC connects to the POP3 server host through a terminal connection that uses a simple protocol (PhoneNet). A program on the PC drives the connection and first sets up a login session as a normal user. The login shell for this pseudo-user is a program that drives the other end of the terminal protocol and talks to one of two servers. MZnet can support several PCs, but there's only one pseudo-user login on the server host. Everyone in MZnet knows the user-id and password for that pseudo-user login. So the first thing the login shell does, after starting the terminal protocol, is demand a USER/PASS authorization pair from the PC. This second level of authorization is how the system figures out who is using the MTS. The server host counts as a "trusted" MTS entity, but the PCs in MZnet do NOT. The USER/PASS pair for a PC is known only to the PC's owner (in theory, at least) ๐Ÿ”

Once the identity of the client has been verified, a modified SMTP server starts up and the PC posts mail to the server host. After the QUIT command is given to the SMTP server and it shuts down, a modified POP3 server starts up and the PC retrieves mail from the server host. After the QUIT command is given to the POP3 server and it shuts down, the pseudo-user's login shell ends the terminal protocol and logs the job out. Then the PC closes the terminal connection to the server host ๐Ÿ“ฌ

The SMTP server used by MZnet is modified so that it knows it's talking to a user agent, NOT to a "trusted" entity in the message transport system. So it does perform the validation steps that an MTS entity normally performs when it accepts a message from a UA ๐Ÿ›ก๏ธ

The POP3 server used by MZnet is modified so that it does not require a USER/PASS combination before entering the TRANSACTION state. The reason is simple: the PC already identified itself during the second-level authorization step we just talked about ๐Ÿ’…

NOTE: Truth in advertising laws mean the author of this memo has to say that MZnet has not actually been fully implemented. The concepts the project presented and proved led to the MZnet split-slot model. That model inspired the split-UA concept described in this memo, shaped the author's interest in POP, and heavily influenced the description of POP3 in here ๐Ÿงช

Some UAs on the Internet already support posting directly to an SMTP server and retrieving mail directly from a POP server, even when the POP server and client are on the same host! ๐Ÿคฏ

ASIDE: This discussion raises an issue that this memo purposely avoids: how does SMTP know that it's talking to a "trusted" MTS entity? ๐Ÿ™ˆ

References ๐Ÿงพโœจ

okay bestie, here are the receipts ๐Ÿ’… every source the spec leans on, all in one place

  • [MZnet] Stefferud, E., J. Sweet, and T. Domae, "MZnet: Mail Service for Personal Micro-Computer Systems", Proceedings, IFIP 6.5 International Conference on Computer Message Systems, Nottingham, U.K., May 1984. ๐Ÿ“ฌ
  • [RFC821] Postel, J., "Simple Mail Transfer Protocol", USC/Information Sciences Institute, August 1982. ๐Ÿ’Œ
  • [RFC822] Crocker, D., "Standard for the Format of ARPA-Internet Text Messages", University of Delaware, August 1982. ๐Ÿ“
  • [RFC937] Butler, M., J. Postel, D. Chase, J. Goldberger, and J. Reynolds, "Post Office Protocol - Version 2", RFC 937, USC/Information Sciences Institute, February 1985. ๐ŸŽ€
  • [RFC1010] Reynolds, J., and J. Postel, "Assigned Numbers", RFC 1010, USC/Information Sciences Institute, May 1987. ๐ŸŒˆ

Author's Address ๐Ÿฆ‹

and this is who wrote the whole thing, the girl behind the POP ๐Ÿซถ

Marshall Rose
The Wollongong Group
1129 San Antonio Rd.
Palo Alto, California 94303

Phone: (415) 962-7100

Email: MRose@TWG.COM

that's the whole document, bestie!! ๐Ÿ’œ๐Ÿงš

๐Ÿ“ฆ where this page comes from