{"id":368,"date":"2018-05-05T19:30:42","date_gmt":"2018-05-05T23:30:42","guid":{"rendered":"https:\/\/www.unliterate.net\/?p=368"},"modified":"2018-05-05T21:41:16","modified_gmt":"2018-05-06T01:41:16","slug":"imapic","status":"publish","type":"post","link":"https:\/\/www.unliterate.net\/index.php\/2018\/05\/05\/imapic\/","title":{"rendered":"IMAP-magic, or iMapic?&#8230;yes?&#8230;no?&#8230;."},"content":{"rendered":"<p>I was given an opportunity to setup an email system for a friend that is similar to mine, so I figured I&#8217;d document this a bit better than what i&#8217;ve been documenting before.<\/p>\n<p>As a primer, this is how we use sendmail, dovecot, and php to get email at a host and have it automatically move messages between email inboxes. Fairly easy \ud83d\ude42<\/p>\n<p>This should be a bit better than my previous partial writeups, specifically <a href=\"https:\/\/www.unliterate.net\/index.php\/2017\/05\/13\/email-heick-email\/\" target=\"_blank\" rel=\"noopener\">email.heick.email<\/a>, <a href=\"https:\/\/www.unliterate.net\/index.php\/2016\/11\/06\/sendmail-dovecot-how-do-you-work\/\">sendmail &#038; dovecot, how do you work&#8230;<\/a>, and <a href=\"https:\/\/www.unliterate.net\/index.php\/2017\/03\/28\/dovecot-imap-part-1\/\" target=\"_blank\" rel=\"noopener\">Dovecot IMAP (part 1)<\/a>.<\/p>\n<p><!--more--><\/p>\n<p>Table of Contents:<\/p>\n<ol>\n<li><a href=\"#base-system-setup\">Base System Setup<\/a><\/li>\n<li><a href=\"#software-installation\">Software Installation<\/a><\/li>\n<li><a href=\"#Dovecot-imap-configuration\">Dovecot IMAP Configuration<\/a><\/li>\n<ol>\n<li><a href=\"#imap-configuration_users\">Users<\/a><\/li>\n<li><a href=\"#imap-configuration_configuration\">Configuration<\/a><\/li>\n<li><a href=\"#imap-configuration_kickoff\">Kickoff<\/a><\/li>\n<li><a href=\"#imap-configuration_debugging\">Debugging<\/a><\/li>\n<\/ol>\n<li><a href=\"#sendmail-configuration\">Sendmail Configuration<\/a><\/li>\n<ol>\n<li><a href=\"#sendmail_local-host-names\">local-host-names<\/a><\/li>\n<li><a href=\"#sendmail_virtusertable\">virtusertable<\/a><\/li>\n<li><a href=\"#sendmail_sendmail-mc\">sendmail.mc<\/a><\/li>\n<li><a href=\"#sendmail_kickoff\">Kickoff<\/a><\/li>\n<li><a href=\"#sendmail_testing\">Testing<\/a><\/li>\n<\/ol>\n<li><a href=\"#service-wrap-up\">Service Wrap-up<\/a><\/li>\n<li><a href=\"#php-automation\">PHP Automation<\/a><\/li>\n<\/ol>\n<p><a name=\"base-system-setup\"><\/a><\/p>\n<h2>Base System Setup<\/h2>\n<p>To make sure I don&#8217;t futz anything up I decided to do a kick-off session in <a href=\"https:\/\/www.virtualbox.org\/\" target=\"_blank\" rel=\"noopener\">VirtualBox<\/a> with a <a href=\"https:\/\/wiki.centos.org\/Download\" target=\"_blank\" rel=\"noopener\">Centos 6.9 base<\/a>. I used the minimal installation media, setup the domain, activated the networking with DHCP, set the root <em>password<\/em>, and got things underway.<\/p>\n<p>After installation was done and the OS was rebooted, I proceeded to create myself a user, visudo that user for godness, set selinux to permissive, and reboot. Some standard maintenance before we proceed with awesomeness.<\/p>\n<p>The commands are pretty much copypasta. As root:<\/p>\n<pre># adduser matt\r\n# passwd matt\r\nChanging password for user matt.\r\nNew password:\r\nBAD PASSWORD: it is based on a dictionary word\r\nRetype new password:\r\npasswd: all authentication tokens updated successfully.\r\n# visudo\r\n...\r\n## Allow root to run any commands anywhere\r\nroot    ALL=(ALL)       ALL\r\nmatt ALL=(ALL) ALL\r\n# shutdown -r now\r\n<\/pre>\n<p>As myself:<\/p>\n<pre>\r\n$ uname -a\r\nLinux niffynoo.vm 2.6.32-696.el6.x86_64 #1 SMP Tue Mar 21 19:29:05 UTC 2017 x86_64 x86_64 x86_64 GNU\/Linux\r\n$ sudo vi \/etc\/selinux\/config\r\nSELINUX=permissive\r\n$ sudo yum update\r\n...tons of yum update stuff\r\n$ sudo shutdown -r now\r\n...shutdown+restart\r\n$ uname -a\r\nLinux niffynoo.vm 2.6.32-696.23.1.el6.x86_64 #1 SMP Tue Mar 13 22:44:18 UTC 2018 x86_64 x86_64 x86_64 GNU\/Linux\r\n<\/pre>\n<p><a name=\"software-installation\"><\/a><\/p>\n<h2>Software Installation<\/h2>\n<p>We know from previous write-ups that we have a base of software to install that will get us our mail server capabilities.<\/p>\n<pre>$ sudo yum install dovecot sendmail cyrus-sasl sendmail-cf cyrus-sasl-devel cyrus-sasl-gssapi cyrus-sasl-md5 cyrus-sasl-plain\r\n...yum installation stuff\r\n$ sudo service sendmail status\r\nsendmail is stopped\r\nsm-client is stopped\r\n$ sudo service dovecot status\r\ndovecot is stopped\r\n$ sudo service saslauthd status\r\nsaslauthd is stopped\r\n<\/pre>\n<p><a name=\"dovecot-imap-configuration\"><\/a><\/p>\n<h2>Dovecot IMAP Configuration<\/h2>\n<p>Dovecots configuration for what we need it to do is fairly straightforward, as we want the *@domain.com setup. All email going to the inbox will eventually be scripted out and delivered to a specific IMAP folder for easy sorting.<\/p>\n<p><a name=\"imap-configuration_users\"><\/a><\/p>\n<h4>Users<\/h4>\n<p>Firstly, we&#8217;ll need a system-level user that has a home folder. This specific user is simply for permissions and resource segregation. Since we&#8217;re on this whole &#8220;magic&#8221;-imap deal, we&#8217;ll keep with the imapic setup. In a real-world scenario<\/p>\n<pre>$ sudo adduser imapic\r\n$ sudo passwd imapic\r\nChanging password for user imapic.\r\nNew password: password\r\nBAD PASSWORD: it is based on a dictionary word\r\nRetype new password: password\r\npasswd: all authentication tokens updated successfully.<\/pre>\n<p>Secondly, we&#8217;re gonna go the cheap route and create a passwd file that allows the user to login with a plaintext username\/password and associate themselves with the system user. It is important in this case to duplicate the uid\/gid from the system user we&#8217;ve created in the previous example. We&#8217;ll manufacture the file in <em>\/etc\/dovecot<\/em> as <em>users<\/em><\/p>\n<pre>\r\n$ id imapic\r\nuid=501(imapic) gid=501(imapic) groups=501(imapic)\r\n$ sudo touch \/etc\/dovecot\/users\r\n$ sudo su\r\n# echo \"imapic:{PLAIN}derp:501:501::\/home\/imapic\" > \/etc\/dovecot\/users\r\n<\/pre>\n<p>So, now there is a system user named imapic with the password <em>password<\/em>, and a dovecot user with the same name but a password of <em>derp<\/em>.<\/p>\n<p>We now need a configuration for dovecot to read the users mail as their inbox.<\/p>\n<p><a name=\"imap-configuration_configuration\"><\/a><\/p>\n<h4>Configuration<\/h4>\n<p>All configurations for dovecot is in <em>\/etc\/dovecot\/conf.d<\/em>. We&#8217;ll just copy\/paste our defacto config into there.<\/p>\n<p>For the sake of config loading and naming, we&#8217;ll call this <em>99-awesome.conf<\/em><\/p>\n<pre>\r\n# This enables imap(143) and imaps(993)\r\nprotocols = imap pop3\r\n\r\n# Setup where we get and store mail at\r\nmail_location = mbox:~\/mail:INBOX=\/var\/mail\/%u\r\n\r\n# related to authentication\r\ndisable_plaintext_auth = no\r\nauth_mechanisms = plain\r\n\r\n# Using a passwordfile\r\n!include auth-passwdfile.conf.ext\r\n\r\n# Set so we can use this from home from more than one device\r\nmail_max_userip_connections = 50\r\n<\/pre>\n<p>The config is actually very easy to read:<\/p>\n<ol>\n<li>Setup protocols to read mail<\/li>\n<li>Setup where we store IMAP folders (in the users home folder under ~\/mail), and what file we determine as the main INBOX (where mail is delivered to)<\/li>\n<li>Setup how we want to authenticate, and include the standard &#8220;passwordfile&#8221; auth configuration<\/li>\n<li>Make it so that we can have multiple connections to the server from the same IP Address<\/li>\n<\/ol>\n<p><a name=\"imap-configuration_kickoff\"><\/a><\/p>\n<h4>Kickoff<\/h4>\n<p>I always like to make sure I&#8217;ve got a message waiting for me, so I&#8217;ll send a dumb email to myself:<\/p>\n<pre>$ echo \"imapic\" | sendmail imapic<\/pre>\n<p>..and i&#8217;ll start dovecot<\/p>\n<pre>$ sudo service dovecot start<\/pre>\n<p>and see if all is okay by talking directly to dovecot:<\/p>\n<pre>$ telnet localhost 143\r\nTrying ::1...\r\nConnected to localhost.\r\nEscape character is '^]'.\r\n* OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE STARTTLS AUTH=PLAIN] Dovecot ready.\r\nA login imapic derp\r\nA OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS MULTIAPPEND UNSELECT CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS] Logged in\r\nB select INBOX\r\nB NO [SERVERBUG] Internal error occurred. Refer to server log for more information. [2018-05-05 17:14:59]\r\nC logout\r\n* BYE Logging out\r\nC OK Logout completed.\r\nConnection closed by foreign host.\r\n<\/pre>\n<p><a name=\"imap-configuration_debugging\"><\/a><\/p>\n<h4>Debugging<\/h4>\n<p>Ah, seems we have an error! It recommends to check error logs located at <em>\/var\/log\/maillog<\/em>:<\/p>\n<pre>$ sudo cat \/var\/log\/maillog\r\nMay  5 17:13:13 dovecot: master: Dovecot v2.0.9 starting up (core dumps disabled)\r\nMay  5 17:14:51 dovecot: imap-login: Login: user=<imapic>, method=PLAIN, rip=::1, lip=::1, mpid=1609, secured\r\nMay  5 17:14:59 dovecot: imap(imapic): Error: chown(\/home\/imapic\/mail\/.imap\/INBOX, -1, 12(mail)) failed: Operation not permitted (egid=501(imapic), group based on \/var\/mail\/imapic)\r\nMay  5 17:14:59 dovecot: imap(imapic): Error: mkdir(\/home\/imapic\/mail\/.imap\/INBOX) failed: Operation not permitted\r\nMay  5 17:15:09 dovecot: imap(imapic): Disconnected: Logged out bytes=24\/435\r\n<\/pre>\n<p>Our mail file is owned by our user, but it needs to also be a member of the same group for dovecot to even think about reading it.<\/p>\n<pre>$ ll \/var\/mail\/imapic\r\n-rw-rw----. 1 imapic mail 599 May  5 17:10 \/var\/mail\/imapic\r\n<\/pre>\n<p>So, lets fix that up:<\/p>\n<pre>$ sudo usermod -G mail imapic\r\n$ id imapic\r\nuid=501(imapic) gid=501(imapic) groups=501(imapic),12(mail)<\/pre>\n<p>and we try again:<\/p>\n<pre>$ telnet localhost 143\r\nTrying ::1...\r\nConnected to localhost.\r\nEscape character is '^]'.\r\n* OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE STARTTLS AUTH=PLAIN] Dovecot ready.\r\nA login imapic derp\r\nA OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS MULTIAPPEND UNSELECT CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS] Logged in\r\nB select INBOX\r\n* FLAGS (\\Answered \\Flagged \\Deleted \\Seen \\Draft)\r\n* OK [PERMANENTFLAGS (\\Answered \\Flagged \\Deleted \\Seen \\Draft \\*)] Flags permitted.\r\n* 1 EXISTS\r\n* 1 RECENT\r\n* OK [UNSEEN 1] First unseen.\r\n* OK [UIDVALIDITY 1525555276] UIDs valid\r\n* OK [UIDNEXT 2] Predicted next UID\r\n* OK [HIGHESTMODSEQ 1] Highest\r\nB OK [READ-WRITE] Select completed.\r\nC logout\r\n* BYE Logging out\r\nC OK Logout completed.\r\nConnection closed by foreign host.<\/pre>\n<p>Perfect! We have access to our inbox and we have 1 mail waiting for us.<\/p>\n<p><a name=\"sendmail-configuration\"><\/a><\/p>\n<h2>Sendmail Configuration<\/h2>\n<p>Sendmail already works like a charm. We just need to tell it about our &#8220;new domain&#8221;, and what to do with messages destined to it.<\/p>\n<p>For all this, we&#8217;re gonna work as <em>root<\/em> and in <em>\/etc\/mail<\/em><\/p>\n<p><a name=\"sendmail_local-host-names\"><\/a><\/p>\n<h4>local-host-names<\/h4>\n<p>This file contains all of the alternate host names of the server (i.e. domain-name.com). Sendmail will not accept mail for a domain unless it is permitted to do so by the contents of this file.<\/p>\n<p>With all that written, we&#8217;ll add our domains in this file.<\/p>\n<p><a name=\"sendmail_virtusertable\"><\/a><\/p>\n<h4>virtusertable<\/h4>\n<p>This file is heavily documented, but it comes down to adding the rule that all mail to the domain goes to the system account that we created back in the dovecot days.<\/p>\n<pre>\r\n...\r\n@domain.com imapic\r\n<\/pre>\n<p>If we wanted mail from derp@domain.com to go to a different system account and not be dropped into the imapic &#8220;public&#8221; box, we&#8217;d add that rule above the one we&#8217;d created.<\/p>\n<p><a name=\"sendmail_sendmail-mc\"><\/a><\/p>\n<h4>sendmail.mc<\/h4>\n<p>This, by far, is just something that I don&#8217;t personally understand. Items would need to be commented or changed to allow specific actions:<\/p>\n<p>Add all the following to the bottom of the file:<\/p>\n<p>Authentication rules:<\/p>\n<pre>define(`confAUTH_OPTIONS', `A')dnl\r\ndefine(`confAUTH_MECHANISMS', `LOGIN PLAIN')dnl\r\nTRUST_AUTH_MECH(`LOGIN PLAIN')dnl<\/pre>\n<p>Allow connections through a primary and secondary port for sending email messages:<\/p>\n<pre>DAEMON_OPTIONS(`Port=25,Name=MTA')dnl\r\nDAEMON_OPTIONS(`Port=587, Name=MSA, M=E')dnl<\/pre>\n<p>To save a headache later on, delete any lines in the <em>sendmail.mc<\/em> that contain any configurations above.<\/p>\n<p>Once you&#8217;ve saved everything, compile:<\/p>\n<pre># \/etc\/mail\/make<\/pre>\n<p><a name=\"sendmail_kickoff\"><\/a><\/p>\n<h4>Kickoff<\/h4>\n<p>As simple as starting\/restarting the services:<\/p>\n<pre># service sendmail start\r\nStarting sendmail:                                         [  OK  ]\r\nStarting sm-client:                                        [  OK  ]\r\n# service saslauthd start\r\nStarting saslauthd:                                        [  OK  ]<\/pre>\n<p>Also, you might want to check if postfix has 25. Stop that if necessary.<\/p>\n<p><a name=\"sendmail_testing\"><\/a><\/p>\n<h4>Testing<\/h4>\n<p>Once you&#8217;ve started everything necessary, test to make sure you can connect and authenticate with the server. It will use system username\/passwords to login, so you can create a test user before telnetting and testing:<\/p>\n<pre>$ sudo adduser test\r\n$ sudo passwd test\r\n...\r\n# telnet localhost 25\r\nTrying 127.0.0.1...\r\nConnected to localhost.\r\nEscape character is '^]'.\r\n220 hostname ESMTP Sendmail 8.14.4\/8.14.4; Sat, 5 May 2018 21:12:03 -0400\r\nHELO derp\r\n250 hostname Hello localhost [127.0.0.1], pleased to meet you\r\nAUTH LOGIN dGVzdA==\r\n334 UGFzc3dvcmQ6\r\ndGVzdA==\r\n235 2.0.0 OK Authenticated\r\nQUIT\r\n221 2.0.0 hostname closing connection\r\nConnection closed by foreign host.\r\n<\/pre>\n<p>dGVzdA==, in base64, is &#8220;test&#8221;. It&#8217;s both the username and password for this specific test account.<\/p>\n<p><a name=\"service-wrap-up\"><\/a><\/p>\n<h2>Service Wrap-up<\/h2>\n<p>Finally, after all this testing and configuration, we need to make sure we don&#8217;t have to do much more maintanance in case of server restart:<\/p>\n<pre>$ sudo chkconfig --level 345 dovecot on\r\n$ sudo chkconfig --level 345 saslauthd on\r\n<\/pre>\n<p><a name=\"php-automation\"><\/a><\/p>\n<h2>PHP Automation<\/h2>\n<p>Part of the magic of all this is to now use the power of scripting to automatically &#8220;move&#8221; all incoming email to specific mailboxes.<\/p>\n<p>So, we&#8217;ll need to install some additional software:<\/p>\n<pre>$ yum install php php-imap<\/pre>\n<p>And, as the all-mighty <em>root<\/em>, we setup <strong>imap-mail-mover.php<\/strong><\/p>\n<pre>&lt;?php\r\n\/**\r\n * The whole purpose of this script is to perform the following:\r\n * 1) Open an IMAP connection to an INBOX\r\n * 2) Look through all the messages\r\n * 3) Grab all messages and look for the first \"To: \" header in each message\r\n * 4) If the person in the \"To: \" is in the allowed domain\r\n * - We grab the user\r\n * - We check to see if their is a mailbox for that user, and move the messge there\r\n * - We delete the message\r\n * 5) If the person is not in the allowed domain\r\n * - We move the message to a default folder\r\n *\/\r\n\r\nfunction get_imap_folders($resource, $config)\r\n{\r\n     \/\/ Get a list of mailboxes\r\n     $original_folders = imap_listmailbox($resource, \"{\" . $config['server'] . \":\" . $config['port'] . \"}\", \"*\");\r\n     \/\/ these come through as {server:port}mailbox, so we just clean them up a bit\r\n     $new_folders = array();\r\n     $to_remove = \"{\" . $config['server'] . \":\" . $config['port'] . \"}\";\r\n     $folders = str_replace($to_remove, \"\", $original_folders);\r\n     return $folders;\r\n}\r\n\r\n$config = array(\r\n     'server' =&gt; 'localhost',\r\n     'port' =&gt; '143',\r\n     'username' =&gt; 'redacted',\r\n     'password' =&gt; 'redacted',\r\n     'folder' =&gt; 'INBOX',\r\n     'spam' =&gt; 'SPAM',\r\n     'debug' =&gt; true,\r\n);\r\n$debug_message = \"\";\r\n\r\n$res = imap_open(\"{\" . $config['server'] . \":\" . $config['port'] . \"\/service=imap\/novalidate-cert\" . \"}\" . $config['folder'], $config['username'], $config['password']);\r\nif (!$res)\r\n{\r\n     if ($config['debug'])\r\n     {\r\n     $debug_message = \"IMAP Stream Failure\";\r\n     }\r\n     die($debug_message);\r\n}\r\n\r\n$folders = get_imap_folders($res, $config);\r\n\r\n\/\/ Lets get all the mail messages in the $config['folder']\r\n$mbox = imap_check($res);\r\n$number_messages = $mbox-&gt;Nmsgs;\r\nif ($number_messages == 0)\r\n{\r\n     if ($config['debug'])\r\n     {\r\n     $debug_message = \"No Messages\";\r\n     }\r\n     die($debug_message);\r\n}\r\n$range = \"1:\" . $number_messages;\r\n\r\n\/\/ now, we'll get the messages\r\n$messages = imap_fetch_overview($res, $range);\r\nforeach ($messages as $msg)\r\n{\r\n     $msgno = $msg-&gt;msgno;\r\n     $to = $msg-&gt;to;\r\n\r\n     echo \"Message: \" . $msg-&gt;subject . \"\\n\";\r\n     if (strpos($to, \"@\"))\r\n     {\r\n          $array_to = explode(\"@\", $to);\r\n          $to = $array_to[0];\r\n     }\r\n\r\n     \/\/ do we need to create a folder to move this message into?\r\n     $destination_mbox = \"{\" . $config['server'] . \":\" . $config['port'] . \"}\" . $to;\r\n     if (!in_array($to, $folders))\r\n     {\r\n          if (imap_createmailbox($res, $destination_mbox))\r\n          {\r\n               echo \"&gt; Created folder [$to]\\n\";\r\n          }\r\n          else\r\n          {\r\n               echo \"&gt; Failed to create folder [$to]\\n\";\r\n          }\r\n     }\r\n     $folders = get_imap_folders($res, $config);\r\n     if (imap_mail_move($res, $msgno, $to))\r\n     {\r\n          echo \"+ Moved successfully\\n\";\r\n     }\r\n     else\r\n     {\r\n          echo \"- Failed to move message\\n\";\r\n     }\r\n}\r\nimap_expunge($res);\r\nimap_close($res);\r\n?&gt;<\/pre>\n<p>and, finally, we set some cron job to execute it:<\/p>\n<pre>\r\n$ crontab -e\r\n# Create folder based on incoming message\r\n*\/1 * * * * \/usr\/bin\/php -f \/root\/imap-mail-mover.php 2>\/dev\/null 1>&2<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>I was given an opportunity to setup an email system for a friend that is similar to mine, so I figured I&#8217;d document this a bit better than what i&#8217;ve been documenting before. As a primer, this is how we use sendmail, dovecot, and php to get email at a host and have it automatically [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[19,20,17],"tags":[],"class_list":["post-368","post","type-post","status-publish","format-standard","hentry","category-centos","category-geek-instructions","category-linux"],"_links":{"self":[{"href":"https:\/\/www.unliterate.net\/index.php\/wp-json\/wp\/v2\/posts\/368","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.unliterate.net\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.unliterate.net\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.unliterate.net\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.unliterate.net\/index.php\/wp-json\/wp\/v2\/comments?post=368"}],"version-history":[{"count":28,"href":"https:\/\/www.unliterate.net\/index.php\/wp-json\/wp\/v2\/posts\/368\/revisions"}],"predecessor-version":[{"id":396,"href":"https:\/\/www.unliterate.net\/index.php\/wp-json\/wp\/v2\/posts\/368\/revisions\/396"}],"wp:attachment":[{"href":"https:\/\/www.unliterate.net\/index.php\/wp-json\/wp\/v2\/media?parent=368"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.unliterate.net\/index.php\/wp-json\/wp\/v2\/categories?post=368"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.unliterate.net\/index.php\/wp-json\/wp\/v2\/tags?post=368"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}