In my previous article on "How to setup unauthenticated mail server configuration using mail forwarding with authentication", I've tried to collate all the steps required to setup Postfix server on RHEL7. Here, I simply automate it.
Why do it manually, when you could do the same with automation for next 5 years.
-- Random Thoughts

#!/bin/sh

######################################################
# This script will enable the linux postfix setup.
# Ensure that mail, postfix and openssl are installed.
# @author cubicrace.com
######################################################

SMTP_HOST=$1
SMTP_PORT=$2

SMTP_USERNAME=$3
SMTP_PASSWORD=$4
POSTFIX_DIR=/etc/postfix
MAIN_CF=${POSTFIX_DIR}/main.cf
HOSTNAME=`hostname`

ERROR(){
  local line=$3
  [ ! -z $3 ] && line=`expr $line - 1` || line=""
  echo "$1, RC=$2, ERROR on line: $line"
  exit $2
}

INFO(){
  echo "$1"
}

addProperty(){
  echo "${1} = ${2}" >> ${3}
  if [ $? -eq 0 ]
  then 
    INFO "Property \"$1\" configured with value \"$2\""
  else
    ERROR "Failed to add property \"$1\"" 2 ${LINENO}
  fi
}

updateProperty(){
  sed -i "s|^$1[[:space:]]*=.*|$1 = $2|g" ${3}
  if [ $? -eq 0 ]
  then
    INFO "Property \"$1\" configured with value \"$2\"" 
  else 
    ERROR "Failed to update property \"$1\"" 2 ${LINENO}
  fi
}

configure(){
  KEY="$1"
  VALUE="$2"
  FILE="$3"
  [ -z ${KEY} ] && ERROR "Invalid or empty property name \"${KEY}\"." 1 ${LINENO}
  [ -z ${FILE} -o ! -f $FILE ] && ERROR "No such file, $FILE" 1 
  grep -q "^[[:space:]]*${KEY}[[:space:]]*=" ${FILE} >/dev/null 2>&1
  rc=$?
  if [ $rc -eq 0 ]
  then
    updateProperty "${KEY}" "${VALUE}" "${FILE}" 
  else 
    addProperty "${KEY}" "${VALUE}" "${FILE}"
  fi
}

encryptAndStoreSMTPCredentials(){
   echo "${1}:${2}    ${3}:${4}" > ${5}
   postmap ${5}
   chown root:root "${5}" "${5}.db"
   chmod 0600 "${5}" "${5}.db"
}

setupTLSPolicy(){
  echo "$1:$2 encrypt" > ${3}
  postmap ${3}
}

getSignerCert(){
  local domain=`echo "$1" | awk -F'.' '{print $(NF-1)"." $NF}'`
  echo -n | openssl s_client -connect $domain:443 | \
  sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' >/tmp/cacertbundle.pem

  if [ $? -eq 0 ]
  then
    cp /tmp/cacertbundle.pem ${POSTFIX_DIR} 
  else 
    INFO "WARNING: Failed to retrieve certificate from host $domain:443"
  fi
}

sendTestMail(){
  TEST_MAILID="$1"
  TEST_MAILSUB="$2"
  TEST_MAILBODY="$3"
  echo "${TEST_MAILBODY}" | mail -s "$TEST_MAILSUB" "$TEST_MAILID"
  echo ""
  echo "Test email has been sent to $TEST_MAILID with subject, \"$TEST_MAILSUB\""
}

USAGE(){
  SCRIPTNAME=`basename $0`
  echo ""
  echo "Usage:"
  echo "$SCRIPTNAME    "
  echo ""
  echo "For example: $SCRIPTNAME 'smtp.gmail.com' '587' 'sysadmin@gmail.com' 'passpass'"
  echo ""
  exit 1
}

[ $# -lt 4 ] && USAGE

encryptAndStoreSMTPCredentials "${SMTP_HOST}" "${SMTP_PORT}" \
"${SMTP_USERNAME}" "${SMTP_PASSWORD}" "${POSTFIX_DIR}/sasl_password"

setupTLSPolicy "${SMTP_HOST}" "${SMTP_PORT}" "${POSTFIX_DIR}/tls_policy"

configure "myhostname" "$HOSTNAME" "${MAIN_CF}"
configure "relayhost" "${SMTP_HOST}:${SMTP_PORT}" "${MAIN_CF}"
echo "/^From:.*/ REPLACE From:$SMTP_USERNAME" > ${POSTFIX_DIR}/smtp_header_checks
configure "smtp_header_checks" "pcre:${POSTFIX_DIR}/smtp_header_checks" "${MAIN_CF}"
configure "smtp_sasl_auth_enable" "yes" "${MAIN_CF}"
configure "smtp_sasl_security_options" "noanonymous" "${MAIN_CF}"
configure "smtp_sasl_tls_security_options" "noanonymous" "${MAIN_CF}"
configure "smtp_sasl_password_maps" "hash:${POSTFIX_DIR}/sasl_password" "${MAIN_CF}"
configure "smtp_tls_policy_maps" "hash:${POSTFIX_DIR}/tls_policy" "${MAIN_CF}"
configure "smtpd_use_tls" "yes" "${MAIN_CF}"
getSignerCert "${SMTP_HOST}"
configure "smtp_tls_CAfile" "${POSTFIX_DIR}/cacertbundle.pem" "${MAIN_CF}"
service postfix restart
sleep 2
sendTestMail "${SMTP_USERNAME}" \
"Test email: Postfix configuration for $HOSTNAME on `date`" \
"This is a test mail generated by the configuration script from 'http://www.cubicrace.com'"


Usage:
./setup_postfix_relay.sh "smtp.gmail.com" "587" "someadmin@gmail.com" "gmail_password_of_someadmin"

Automated linux shell script to setup Postfix on RHEL7 with Gmail



We want to send mails which are authenticated by a mail server, but the application can only send mails to a unauthenticated mail server. We achieve this end result of authenticated mails, by using postfix (a mail relay/forwarding tool ).

What is Postfix? Its a mail server program written by "Wietse Zweitze Venema" that started life at IBM Research as an alternative to the most popular linux "Sendmail" tool. Now he works at Google,  and continues to support Postfix.

Postfix attempts to be fast, easy to setup, and secure. After using postfix you may feel that it's just a sendmail tool, but from inside its completely different. Most Linux OS would have postfix installed by default, if not you can install it using yum or apt-get based on your OS. Before setting up postfix make sure you also have the mail tool installed. Lets try to go through the flow we want to achieve.



Configuration Steps (RedHat):
1. Install the tools
yum update && yum install postfix mailx

2. Setup Gmail Authentication
Create or modify a credentials file which will be used by Postfix to establish authentication with GMail or any other mail server.
Add your credentials to a file (these are the details of the "mail from" user)
echo  "[smtp.gmail.com]:587     starkadmin@gmail.com:password" >/etc/postfix/sasl_passwd

3. Secure this credentials file
chmod 600 /etc/postfix/sasl_passwd
postmap /etc/postfix/sasl_passwd

4. Create the security configurations file and secure it
echo "smtp.gmail.com:587   encrypt" >/etc/postfix/tls_policy
postmap /etc/postfix/tls_policy

5. Fetch the remote server's signer certificate
Note: Its a one line command
echo  -n | openssl  s_client  -connect  gmail.com:443 | \
sed  -ne  '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p'  >/etc/postfix/cacert.pem

6. Create the mail re-write policy file
The file /etc/postfix/smtp_header_checks contains rules to be used to rewrite the headers of the emails about to be sent.
This is the most important file in our case as it rewrites the sender so that it always matches our GMail account, starkadmin@gmail.com
No more 'Relaying disallowed' errors!
echo  "/^From:.*/   REPLACE  From:starkdmin@gmail.com" > /etc/postfix/smtp_header_checks

7. Configure postfix
Edit postfix configuration file /etc/postfix/main.cf with following values:
relayhost = smtp.gmail.com:587
smtp_header_checks = pcre:/etc/postfix/smtp_header_checks
smtp_sasl_auth_enable = yes
smtp_sasl_security_options = noanonymous
smtp_sasl_tls_security_options = noanonymous
smtp_sasl_password_maps = hash:/etc/postfix/sasl_password
smtp_tls_policy_maps = hash:/etc/postfix/tls_policy
smtpd_use_tls = yes
smtp_tls_CAfile = /etc/postfix/cacert.pem

8. Enable IMAP for gmail user's (eg: starkadmin@gmail.com) account.

9. Restart postfix service and send a sample mail
service restart postfix

10. Enable "Less Secure Apps" In GMail
By default, only the most secure sign-ins, such as logging in to GMail on the web, are allowed for your GMail account. To permit relay requests, log in to your GMail account and turn on Allow less secure apps. For more information, review the Google Support document
"Allowing less secure apps to access your account."

11. All DONE
Let's send a test mail to confirm all our efforts...
echo  "This mail is generated by the configuration steps from 'http://www.cubicrace.com'"  |  mail  -s  "Postfix configuration" "piyush@cubicrace.com"

Troubleshooting
For postfix log, see /var/log/maillog

Still not working, try this ...
In the file /etc/postfix/master.cf, I uncommented this line:
smtps  inet  n  -  -  -  -  smtpd

Thinking to automate this ?
Here's a script to do all the above steps in a ONE single script !
http://www.cubicrace.com/2017/11/automate-script-postfix-setup.html

How to setup unauthenticated mail server configuration using mail forwarding with authentication



Where Good Ideas come from ? ... by Steven Jhonson.
A Fantastic video filled with loads of real life examples and inspirational thoughts....


Good Ideas by Smarter people for a Smarter planet


Archives are the heart and history of any blog. While the recent blog posts appear on the blog's home page, older posts are harder to find. Thanks to the archiving feature, so that the older posts can be found online at any time in the future...


Archive


In WEB based applications RESTful APIs are used to manipulate data between the browser and the server. User may enter some data which is formatted to a valid JSON object (Java Script Object Notation) before sending it to the server for processing. However at the server side this data may be stored in an XML format, which means we need to now convert this data from JSON to XML and vice-versa while sending data from server to the browser.

Below is a screenshot showing a sample XML on the left side and the generated JSON on the right side:


Conversion of JSON to XML isn't straight forward since they don't share common aspects about their structure. One may write a parser to read JSON elements one by one and then generate an XML but its a tedious job. Thanks to the power of Java Architecture for XML Binding (JAXB) which can easily parsing of XML (based on its dtd - document type definition) ie: convert an XML string into a java object and vice-versa. However pure jaxb implemetation isin't sufficient to solve our problem. We need a third party library named eclipselink.jar (download from here) which has the jaxb implementation to convert XML to JSON and vice versa. Alternatively we can use 3 sub jars from the eclipselink.jar - org.eclipse.persistence.core-2.5.1.jar, org.eclipse.persistence.antlr-2.5.1.jar, org.eclipse.persistence.moxy-2.5.1.jar

Steps:
1. Generate java classes using the dtd file of the XML
/usr/java/jdk1.7.0_60/bin/xjc
-dtd /home/cubicrace/workspace/json2xml/samples/DatabaseInventory.dtd
-d /home/cubicrace/workspace/json2xml/src/
-p com.utilities.jaxb

parsing a schema...
compiling a schema...
com/utilities/jaxb/Administrator.java
com/utilities/jaxb/DatabaseAttributes.java
com/utilities/jaxb/DatabaseInventory.java
com/utilities/jaxb/DatabaseName.java
com/utilities/jaxb/ObjectFactory.java


2. Create a jaxb.properties file with the below content:
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

Ensure that this file exists at the same location as the .class files of the above generated java files.

3. Add the eclipselink.jar to the classpath or project's java build path

4. Write a simple class to perform the conversion.
Below is a working standlone class:


package com.utilities;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

import org.eclipse.persistence.jaxb.MarshallerProperties;
import org.eclipse.persistence.jaxb.UnmarshallerProperties;

import com.utilities.jaxb.DatabaseInventory;

public class JsonXmlConverter {

 public static final String base = "/home/cubicrace/workspace";
 
 static String srcJsonFile = base + "/json2xml/samples/dbInventory.json";
 static String srcXmlFile = base +  "/json2xml/samples/dbInventory.xml";    
 static String convertedJsonFile = base + "/json2xml/samples/convertedFile.json";
 static String convertedXmlFile = base + "/json2xml/samples/convertedFile.xml";
 
 public boolean createFile(String filePath) {
  File file = new File(filePath);
  file.delete();
  try {
   return file.createNewFile();
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
   return false;
  }
 }
 
 private void jsonToXml(String jsonFile) throws Exception{
  File jsonObj = new File(jsonFile);
  JAXBContext jc = JAXBContext.newInstance(DatabaseInventory.class);
  Unmarshaller unmarshaller = jc.createUnmarshaller();
  unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, "application/json");
  DatabaseInventory activity = (DatabaseInventory) unmarshaller.unmarshal(jsonObj);
  
  Marshaller xmlM = jc.createMarshaller();
  xmlM.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
  FileOutputStream fos = new FileOutputStream(new File(convertedXmlFile));
  xmlM.marshal(activity, fos);
  fos.close();
 }
 
 private void xmlToJson(String xmlFile) throws Exception{
  File xml = new File(xmlFile);
  JAXBContext jc = JAXBContext.newInstance(DatabaseInventory.class);
  Unmarshaller unmarshaller = jc.createUnmarshaller();
  DatabaseInventory activity = (DatabaseInventory) unmarshaller.unmarshal(xml);

  Marshaller marshaller = jc.createMarshaller();
  marshaller.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, true);
  marshaller.setProperty( MarshallerProperties.MEDIA_TYPE, "application/json");
  marshaller.setProperty( MarshallerProperties.JSON_INCLUDE_ROOT, true);
  FileOutputStream fos = new FileOutputStream(new File(convertedJsonFile));
  marshaller.marshal(activity, fos);
  fos.close();
 }
 
 public static void main(String[] args) {

  JsonXmlConverter jxc = new JsonXmlConverter();
    
  try {
   jxc.createFile(convertedJsonFile);
   System.out.println("Source XML: " +  srcXmlFile);
   jxc.xmlToJson(srcXmlFile);
   System.out.println("Converted Output JSON: " + convertedJsonFile);
   
   jxc.createFile(convertedXmlFile);
   System.out.println("Source JSON: " + srcJsonFile);
   jxc.jsonToXml(srcJsonFile);
   System.out.println("Converted Output XML: " + convertedXmlFile);
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  
 }

}


Note: Ensure to update the workspace variable in the above java class before executing in your local environment.

If you see the below error, it means the jaxb.properties file (step2 above) is missing at the expected location or has incorrect property value pair.
javax.xml.bind.PropertyException: name: eclipselink.media-type value: application/json
at javax.xml.bind.helpers.AbstractMarshallerImpl.setProperty(AbstractMarshallerImpl.java:337)
at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.setProperty(MarshallerImpl.java:539)

Download the dtd, sample files, eclipselink.jar and source code as single zip: here

How to convert a given XML snippet to an equivalent JSON format and vice-versa

The RBI will soon be issuing ₹ 2000 denomination banknotes in the Mahatma Gandhi (New) Series, without the inset letter, bearing signature of Dr. Urjit R. Patel, Governor, Reserve Bank of India, and the year of printing '2016' printed on the reverse of the banknote.

The new denomination has picture of Mangalayan on the reverse, depicting the country’s first venture into the interplanetary space. The base colour of the note is magenta. The note has other designs like geometric patterns aligning with the overall colour scheme, both at the obverse and reverse.

RBI's website doesn't mention anything about the NGC chip embedded in the currency ... Seems like a rumour/fake news.

Certain rumours about the 2000 currency note:
  1. Apparently, the new notes will have nano-GPS chips installed on them, for tracking. These chips will reportedly allow satellites to track the currency, even at 120 metres below ground level.
  2. Further, rumours say that the nano-GPS chips work without any power source, which is quite interesting if true.
  3. Moreover, the satellites will reportedly track large amounts of money stored at any place, automatically, and pass on the information to the Income Tax department.
  4. The department can then track such currency and recover it, if it’s found to be illegal.
  5. Removing the nano-GPS will reportedly render the currency unusable in the first place. 

Tracking currency may not be true, WHY ? 

1. Real Fact:
World’s smallest fully integrated GPS receiver has been developed by OriginGPS Nano Spider, which measures 4 x 4 x 2.1 mm. Comparably, this device is really small (but not smaller than a currency note), and can open a new avenue of wearable devices – now this chip can track clothes, watches, electronic appliances and more. However thickness of 2.1mm is big to fit in a currency note which is 0.1-0.2 mm thick.

2. Common PHYSICS:
GPS satellites are located in the medium earth orbit which starts at 20,200 Kilometers from Earth's surface, so deflecting a signal that far without any energy is impossible (https://en.wikipedia.org/wiki/GPS_satellite_blocks). If this was an available technology, it would have been used in mobile phones and there was no need to use the A-GPS ( which uses your mobile's data connection and GPS sensor to detect your mobile's location )

3. Link to RBI's site for details about the ₹2000 note:
 https://rbidocs.rbi.org.in/rdocs/PressRelease/PDFs/PR1144EFECD860ED0D479D88AB8D5CA036FC35.PDF

4. A chip without any power source will be able to embed the currency series number to the received GPS signal and deflect it back ???  this is beyond imagination and against science laws ... 


Front Features (As seen on RBI website)
  1. See through register with denominational numeral 2000
  2. Latent image with denominational numeral 2000
  3. Denominational numeral २००० in Devnagari
  4. Portrait of Mahatma Gandhi at the centre
  5. Micro letters ‘RBI’ and ‘2000’ on the left side of the banknote
  6. Windowed security thread with inscriptions ‘भारत’, RBI and 2000 on banknotes with colour shift. Colour of the thread changes from green to blue when the note is tilted
  7. Guarantee Clause, Governor’s signature with Promise Clause and RBI emblem towards right
  8. Denominational numeral with Rupee Symbol, ₹2000 in colour changing ink (green to blue) on bottom right 
  9. Ashoka Pillar emblem on the right
  10. Mahatma Gandhi portrait and electrotype (2000) watermarks
  11. Number panel with numerals growing from small to big on the top left side and bottom right side
    For visually impaired
    Intaglio or raised printing of Mahatma Gandhi portrait, Ashoka Pillar emblem, bleed lines and identity mark
  12. Horizontal rectangle with ₹2000 in raised print on the right
    Seven angular bleed lines on left and right side in raised print 
Reverse Features (As seen on RBI website)
  1. Year of printing of the note on the left
  2. Swachh Bharat logo with slogan
  3. Language panel towards the centre
  4. Motif of Mangalayan
  5. Denominational numeral २००० in Devnagari

India - Nano GPS chip or NGC in currency

+